[英]Returning all results in where in clause (Sql Server)
我有一張如下表:
Book BookSales Date
BookA $1 2013-03-04
BookB $2 2013-03-04
BookA $3 2013-03-05
......
我運行查詢 -
select book,booksales,date
from tblBook
where date>='03/03/2013'
and date<='03/05/2013'
and book in ('BookA','BookB')
order by date,book
現在它返回如下結果
BookA $1 2013-03-04
BookB $2 2013-03-04
BookA $3 2013-03-05
但我想要的是返回書b的空結果($ 0),如果該日期不存在,如下所示)。 此處,日期2013-03-05中不存在圖書b的記錄。
BookA $1 2013-03-04
BookB $2 2013-03-04
BookA $3 2013-03-05
BookB $0 2013-03-05 <-- I want to include this record
我怎樣才能做到這一點? 如果不可能實現這種方式,我還可以考慮采用其他方法嗎?
必須有一種更簡單的方法來做到這一點,但這就是我想出的。 使用公用表表達式獲取不同的日期列表和不同的書籍列表,然后CROSS JOIN
它們以獲得完整的日期和書籍矩陣。 一旦你得到了完整的矩陣,你可以OUTER JOIN
你的表到它,用0替換任何空值。
交叉連接可能會很快變得混亂,但如果它只是一個日期列表和書籍列表,它應該可以正常工作。
;with dates AS
(
select distinct date
from tblBook
), books AS
(
select distinct book
from tblBook
)
select b.book, coalesce(tb.booksales, 0), d.[date]
from dates as d
cross join books as b
left outer join tblBook as tb
on d.[date] = tb.[date]
and b.book = tb.book
where d.[date] >='03/03/2013'
and d.[date] <='03/05/2013'
and b.book in ('BookA','BookB')
order by d.[date], b.[book]
您可以使用子查詢來解決您的問題,該子查詢生成您需要報告的所有不同值。 我假設輸出應該提供一種方法來跟蹤每天每本書的銷售情況,即使沒有在表格中輸入銷售交易。 這是一個可能的解決方案和輸出:
通過構造表示所有可能值的sub query
無論它們是否已存在於表中),可以sub query
查詢表中沒有物理表示的數據值的請求。
在這種情況下,報告的兩個維度是:“book”和“date”。 對於書籍銷售表中記錄的每一天的交易,每本書必須有一個總銷售額條目。
假設:在示例中tblBook
表示已經聚合的銷售額,或者是否可以存在給定“書籍”和“日期”組合的多個記錄...如記錄每個銷售的交易記錄的樣式當他們發生。 解決方案查詢匯總銷售額,以便為每天的每本書提供單個記錄。
注意:此示例在MySQL RDBMS上進行了測試。 此示例中使用的SQL是ANSI標准,因此它也應該在SQLServer數據庫上工作。 您可能必須找到與此解決方案中使用的
ifNULL()
函數等效的函數
SQL代碼
SELECT REPORTING_DIMENSIONS.book,
sum(ifNULL(sales_data.bookSales,0)) as totalSales,
REPORTING_DIMENSIONS.date
FROM
(SELECT book_list.book, date_list.date
FROM
(SELECT distinct book
FROM tblBook
) book_list
CROSS JOIN
(SELECT distinct date
FROM tblBook
) date_list
) REPORTING_DIMENSIONS
LEFT JOIN tblBook SALES_DATA
ON REPORTING_DIMENSIONS.book = SALES_DATA.book
AND REPORTING_DIMENSIONS.date = SALES_DATA.date
GROUP BY REPORTING_DIMENSIONS.book,
REPORTING_DIMENSIONS.date
輸出:
| BOOK | TOTALSALES | DATE |
|-------|------------|------------------------------|
| BookA | 2 | March, 04 2013 00:00:00+0000 |
| BookA | 6 | March, 05 2013 00:00:00+0000 |
| BookB | 4 | March, 04 2013 00:00:00+0000 |
| BookB | 0 | March, 05 2013 00:00:00+0000 |
BookB在2013-03-15的零值實際上是一個NULL值。 當進行OUTER(即,LEFT)連接時,對於連接值沒有匹配,返回null。
唯一奇特的步驟是CROSS JOIN
指定。 也稱為CARTESIAN PRODUCT
,它為現有表格中記錄的每個可能的“書籍”和“日期”組合生成記錄。
子查詢別名為REPORTING DIMENSIONS
是查詢的固定動態特征。 它允許查詢在新書或日期添加到其范圍時調整其輸出。
其他考慮因素:
在報告查詢范圍內包含的一個,所有或許多日歷日內,可以沒有任何產品銷售。 這將再次影響原始報表查詢的輸出,因為結果輸出中將存在漏洞。
這可以通過為日期值創建固定維度表來解決。 在銷售數據范圍之前和之后的幾年內,預先填寫每個離散日歷日的記錄。 帶有循環插入操作的簡單T / SQL塊可以輕松填充此表。 一旦填充完畢,就不太可能需要觸摸它。
如果你有這個
Book BookSales Date
BookA $1 2013-03-04
BookB $2 2013-03-04
BookA $3 2013-03-06
並希望
BookA $1 2013-03-04
BookB $2 2013-03-04
BookA $0 2013-03-05
BookB $0 2013-03-05
BookA $3 2013-03-06
BookB $0 2013-03-06
從傑夫羅森伯格的答案和t-sql被盜獲得2個日期之間的所有日期
;WITH dates AS
(
SELECT CAST('2013-03-04' AS DATETIME) AS [date]
UNION ALL
SELECT DATEADD(dd, 1, [date])
FROM dates s
WHERE DATEADD(dd, 1, [date]) <= CAST('2013-03-06' AS DATETIME)), books AS
(
select distinct book
from tblBooks
)
select b.book, coalesce(tb.booksales, 0), d.[date]
from dates as d
cross join books as b
left outer join tblBooks as tb
on d.[date] = tb.[date]
and b.book = tb.book
如果你需要聚合
...
SELECT b.Book, COALESCE(SUM(tb.BookSales), 0), d.[Date]
FROM Dates d
CROSS JOIN Books b
LEFT JOIN tblBooks tb ON d.[Date] = tb.Date
AND b.Book = tb.Book
GROUP BY b.Book, d.[Date]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.