簡體   English   中英

返回所有結果in子句(Sql Server)

[英]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]

在這里使用SQLFiddle

使用維度子查詢和外部聯接SQL解決缺失的聚合數據

您可以使用子查詢來解決您的問題,該子查詢生成您需要報告的所有不同值。 我假設輸出應該提供一種方法來跟蹤每天每本書的銷售情況,即使沒有在表格中輸入銷售交易。 這是一個可能的解決方案和輸出:

問題分析:

通過構造表示所有可能值的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM