請問這個sql邏輯怎麼寫?

時間 2021-05-10 09:36:06

1樓:拯救夢想

先確定解題思路:乙個可行的辦法是列舉 start_date 和 end_date 兩個日期之間的所有日期,最後通過 brand 字段分組統計所有不重複日期的數量。

題主的資料庫環境應該是 Oracle,其他答主的回答裡面已經提到了使用 connect by 或者借助數字輔助表生成目標範圍內的日期。

我提供另外一種實現方式,就是用遞迴生成所有目標範圍內的日期。下面的 SQL 在 MySQL 8.0 上可直接執行。

WITH

recursivet0(

brand

,start_date

,end_date)AS

(SELECT

brand

,start_date

,end_date

FROM

tUNION

ALLSELECT

brand

,DATE_FORMAT

(DATE_ADD

(start_date

,INTERVAL

1DAY

),'%Y%m%d')AS

start_date

,end_date

FROM

t0WHERE

start_date

)SELECT

brand

,COUNT

(DISTINCT

start_date)AS

cntFROM

t0GROUP

BYbrand

輸出結果 >>>

brand

cnt------

--------A13

B12C18

2樓:劉鑫

Oracle的話應該有遞迴查詢吧(Common Table Expression 的 recursive 支援),那麼就是乙個遞迴查詢能解決的。

3樓:

這個截圖是sql developer了。你desc table_name 給我看看資料型別。一般應該寫個函式把開始時間和結束時間之間的日期算出來, 這裡有個設計理念的問題,有人會說,如果是日期型,oracle自帶日期計算,但是自己寫個函式,之後擴充套件性好。

萬一業務人員之後要求只計算工作日,或者什麼特殊的要求,就可以只改乙個函式了。

然後如果不考慮效率

select brand, sum(tmp)from (select brand, 函式(start,end) as tmp from table_name)

group by brand

4樓:青染

SQL 我就不寫了,提供一下簡單的思路.

CONNECT BY ROWNUM<=trunc(to_date('結束','yyyy-MM-dd')-to_date('開始','yyyy-MM-dd'))

用connect by 和 group by 和 group_concat 獲取活動類別所有開始和結束的時間內的具體天數,然後去重相同的時間.得到的就是所有的活動開始範圍內的時間

5樓:timlcy

Oracle有lag語法,能對比上一行,對比上一行的end是否小於或者等於當前行start,如果是使用當前行end-start,不是則為0

還要多做幾次判斷

SELECT

sum(cz),BRAND from

(SELECT

(case when a_END_DATE>=START_DATE and a_END_DATE<=END_DATE then GREATEST(a_END_DATE,END_DATE)-LEAST(a_START_DATE,START_DATE) +1

when a_END_DATE<=START_DATE and SUMBRAND>2 then END_DATE-START_DATE +1

when a_END_DATE>=END_DATE then a_END_DATE-a_START_DATE+1

else END_DATE-START_DATE +1+a_END_DATE-a_START_DATE+1

end) as cz,a1.*

FROM

SELECT

lag ( START_DATE, 1, NULL ) OVER ( PARTITION BY brand ORDER BY START_DATE ) AS a_START_DATE,

lag ( END_DATE, 1, NULL ) OVER ( PARTITION BY brand ORDER BY START_DATE ) AS a_END_DATE,

START_DATE,

END_DATE,

BRAND,

count(*) OVER( PARTITION BY brand) as SUMBRAND

FROM

TEST1111

) a1

WHERE a_START_DATE is not null

GROUP BY BRAND

6樓:飛鳥

由於Mysql沒有Oracle的connect by,我平時會常備乙個『序列表』,這個表用於儲存1到數百的連續整數。以前建這個表seq時我插入了700多行,夠你的例子啦(如果不夠,比如你某一行的時間跨度大於700多天,增加seq的行數即可)。

mysql> desc seqField | Type | Null | Key | Default | Extraid | int(6) | NO | PRI | NULL | auto_increment |

| r | char(1) | YESNULL2 rows in set (0.03 sec)

mysql> select * from seq limit 10id | r1 | 1 |

| 2 | 1 |

| 3 | 1 |

| 4 | 1 |

| 5 | 1 |

| 6 | 1 |

| 7 | 1 |

| 8 | 1 |

| 9 | 1 |

| 10 | 110 rows in set (0.02 sec)

mysql> select count(*) from seqcount7471 row in set (0.02 sec)

-- 再生成你的表

mysql> desc pField | TypeNull | Key | Default | Extrabrand | varchar(20) | NOsd | dateYESNULLed | dateYESNULL3 rows in set (0.02 sec)

mysql> select * from pbrand | sdeda | 2018-09-01 | 2018-09-05 |

| a | 2018-09-03 | 2018-09-06 |

| a | 2018-09-09 | 2018-09-15 |

| b | 2018-08-04 | 2018-08-15 |

| b | 2018-08-04 | 2018-08-05 |

| c | 2018-08-15 | 2018-08-21 |

| c | 2018-09-02 | 2018-09-127 rows in set (0.02 sec)

-- 用你的表p左連線序列表seq,生成每個活動的不同日期。

mysql> select distinct brand,date_add(p.sd,interval s.id-1 day) dt from p

left join seq s on date_add(p.sd,interval s.id-1 day)>=p.

sdand date_add(p.sd,interval s.id-1 day)<=p.

ed order by brand,dtbrand | dta | 2018-09-01 |

| a | 2018-09-02 |

| a | 2018-09-03 |

| a | 2018-09-04 |

| a | 2018-09-05 |

| a | 2018-09-06 |

| a | 2018-09-09 |

| a | 2018-09-10 |

| a | 2018-09-11 |

| a | 2018-09-12 |

| a | 2018-09-13 |

| a | 2018-09-14 |

| a | 2018-09-15 |

| b | 2018-08-04 |

| b | 2018-08-05 |

| b | 2018-08-06 |

| b | 2018-08-07c | 2018-09-10 |

| c | 2018-09-11 |

| c | 2018-09-1243 rows in set (0.02 sec)

-- 於是,每個brand的活動天數如下:

mysql> select brand,count(*) from (

select distinct brand,date_add(p.sd,interval s.id-1 day) dt from p

left join seq s on date_add(p.sd,interval s.id-1 day)>=p.sd

and date_add(p.sd,interval s.id-1 day)<=p.ed) t group by brandbrand | counta13 |

| b12 |

| c183 rows in set (0.02 sec)

注1 left join 也可以用普通join替換: select .... from p,seq where ....

注2 如果是Oracle,這個seq序列可以用connect by直接生成,就更方便啦。

-- 在oracle中,生成乙個序列是一句話的事。

select level from dual connect by level<5;12

34-- 所以,上述查詢中的seq不需要預先建,可以直接用sql替換

.... from p left join (select level id from dual connect by level<=100)seq on更近一步,select level from dual connect by level<100可以優化成:

select level from (select max(ed)-min(sd)+1 m from p) t connect by level<=m

求問,這個用python怎麼寫???

十字曲軸V8 同小白 usr bin env python3 coding utf 8 defsn check str if len str 9 print 學號檢測失敗,請檢查輸入格式!else if str 1 1 sgrade 1年級 elif str 1 2 sgrade 2年級 elif ...

這個文我是跟風寫的,請問這個套路市場怎麼樣?

周岳 僅僅從目前我看的這些東西來說,寫的不錯!但是還有很多東西我沒看到,不知道你的火候怎麼樣。創意不錯,能把這種感覺繼續寫下去,而且其他地方也不拉跨,那就成了。給你指乙個拉跨的地方 對女性的描寫 很明顯你不太擅長,而且我猜測你也不太擅長其他有關畫面感的描寫。比如打鬥之類的。如果被我猜對了,就多去補一...

請問這個方程怎麼解?

substeps999999 五次方程沒有解析解,數值解裡面也沒有0這個解,原因很簡單 因為你構造二式的時候兩端同時乘a,成了乙個六次方程,比原來的五次方程多了乙個新的解a 0,給你處理一下,構造了另乙個六次方程,這個新解就變成了a 1。這可不是原來那個五次方程的解啊 如勝 這題是出題的出錯了,自做...