我有下表:
Date Type Amount
Jul-17 Type A 20
Jul-17 Type B 30
Jul-17 Type C 10
Aug-17 Type A 50
Aug-17 Type D 40
Aug-17 Type C 70
我的查询只会过滤两个月,如下所示:
SELECT DATE,Type,Amount FROM Table 1 WHERE DATE> =' 01-Jul-2017' 和日期< =' 2017年8月31日'
我想显示7月份不存在的类型,并显示8月份不存在的金额0和类型,并显示金额0如下:
Date Type Amount
Jul-17 Type A 20
Aug-17 Type A 50
Jul-17 Type B 30
Aug-17 Type B 0
Jul-17 Type C 10
Aug-17 Type C 70
Jul-17 Type D 0
Aug-17 Type D 40
到目前为止,我在下面尝试过,但它影响了性能。我想在不使用union的情况下简化查询:
SELECT DATE, Type, Amount
FROM Table 1
WHERE DATE >= '01-Jul-2017'
AND DATE <= '31-Aug-2017'
Union
SELECT '01-Jul-2017' AS DATE, TYPE, 0 AS AMOUNT
WHERE DATE >= '01-Aug-2017'
AND DATE <= '31-Aug-2017'
AND Type NOT in (SELECT DISTINCT TYPE WHERE DATE >= '01-Jul-2017'
AND DATE <= '31-Jul-2017')
Union
SELECT '01-Aug-2017' AS DATE, TYPE, 0 AS AMOUNT
WHERE DATE >= '01-Jul-2017'
AND DATE <= '31-Jul-2017'
AND Type NOT in (SELECT DISTINCT TYPE WHERE DATE >= '01-Aug-2017'
AND DATE <= '31-Aug-2017')
答案 0 :(得分:1)
您可以使用交叉联接来获取所有可能的组合,然后使用左外连接来获取实际数量...
WITH cte
AS ( SELECT DISTINCT
t1.Date ,
t2.Type
FROM dbo.Table1 t1
CROSS JOIN dbo.Table1 t2
WHERE t1.Date BETWEEN '2017-07-01' AND '2017-08-31'
AND t2.Date BETWEEN '2017-07-01' AND '2017-08-31'
)
SELECT cte.Date ,
cte.Type ,
COALESCE(t.Amount, 0) AS Amount
FROM cte
LEFT OUTER JOIN dbo.Table1 AS t ON t.Date = cte.Date
AND t.Type = cte.Type;
答案 1 :(得分:0)
在开始时,我误导了你的标签,并认为你应该为MYSQL做道歉(道歉)。我最后留下了MYSQL版本。 为简洁起见,我使用了*。请用最终查询的全名列表进行更改。
这是MSSQL VERSION 您需要一次指定两个日期(在开头)。 我用TN作为表名。
WITH TT AS (SELECT *, MONTH(DATE) AS MN from TN WHERE DATE >= '2017-07-01' AND DATE <= '2017-08-31' )
SELECT COALESCE(C.DATE, CASE WHEN C.MN2=MINMN THEN DATEADD(MONTH,+1, C.DATE2) ELSE DATEADD(MONTH,-1, C.DATE2) END) AS DATE
, COALESCE(C.TYPE, C.TYPE2) AS TYPE
, COALESCE(C.AMOUNT,0) AS AMOUNT
FROM
(SELECT A.*, B.DATE AS DATE2, B.TYPE AS TYPE2, B.AMOUNT AS AMOUNT2, B.MN AS MN2, X.MINMN
from TT A
FULL JOIN TT B ON A.MN<>B.MN AND A.TYPE = B.TYPE
CROSS JOIN (SELECT MIN(MN) MINMN FROM TT) X
)C
ORDER BY DATE, TYPE ;
输出:
DATE TYPE AMOUNT
1 17.07.2017 00:00:00 A 20
2 17.07.2017 00:00:00 B 30
3 17.07.2017 00:00:00 C 10
4 17.07.2017 00:00:00 D 0
5 17.08.2017 00:00:00 A 50
6 17.08.2017 00:00:00 B 0
7 17.08.2017 00:00:00 C 70
8 17.08.2017 00:00:00 D 40
MYSQL VERSION 我刚刚找到这个(它只使用一个UNION,而不是两个)。 我用TN作为表名。请检查一下表演。
SELECT * from TN WHERE DATE >= '2017-07-01' AND DATE <= '2017-08-31'
UNION ALL
SELECT CASE WHEN MONTH(A.DATE)=M1 THEN '2017-08-01' ELSE '2017-07-01' END AS DATE, A.TYPE, 0 AS AMOUNT
from TN A
LEFT JOIN (SELECT * FROM TN WHERE DATE >= '2017-07-01' AND DATE <= '2017-08-31') B ON DATE_FORMAT(A.DATE ,'%Y-%m-01') <> DATE_FORMAT(B.DATE ,'%Y-%m-01') AND A.TYPE = B.TYPE
CROSS JOIN (SELECT MIN(MONTH(DATE)) AS M1 FROM TN WHERE DATE >= '2017-07-01' AND DATE <= '2017-08-31') X
WHERE A.DATE >= '2017-07-01' AND A.DATE <= '2017-08-31'
AND B.TYPE IS NULL
输出:
Date type amount
1 2017-07-17 A 20
2 2017-07-17 B 30
3 2017-07-17 C 10
4 2017-08-17 A 50
5 2017-08-17 D 40
6 2017-08-17 C 70
7 2017-08-01 B 0
8 2017-07-01 D 0
答案 2 :(得分:0)
如果您想使用pivot执行结果。 您可以尝试以下查询:
select [Date] As Date_For_Table,
[Type A] =
case
when [Type A] IS NULL Then 0
else [Type A]
end,
[Type B] =
case
when [Type B] IS NULL Then 0
else [Type B]
end,
[Type C] =
case
when [Type C] IS NULL Then 0
else [Type C]
end,
[Type D] =
case
when [Type D] IS NULL Then 0
else [Type D]
end
from
(
select CONVERT(CHAR(4), date, 100) + CONVERT(CHAR(4), date, 120) as date ,type,Amount
from Table1
) as PivotData
pivot
(
avg(amount) for type in
([Type A],[Type B],[Type C],[Type D]))as Pivoting
order by date desc