2010-06-21 334 views
9

如何返回兩列,每列使用不同的WHERE關鍵字?顯然,這是行不通的:SQL兩列不同WHERE條件爲兩列

SELECT Name, COUNT(Column1) AS Total, COUNT(Column1) AS YearToDate 
FROM Table1 
WHERE Occurred_Date BETWEEN '2010-06-01' AND '2010-06-30' --Total 
WHERE Occurred_Date BETWEEN '2010-01-01' AND '2010-06-30' --YearToDate 

這就是我要找的輸出:

Name | Total | YTD 
------------------- 
Item1 | 2  | 3 
Item2 | 4  | 8 
+0

不確定在結果集中沒有發生衝突的情況下是否有可能。 – VoodooChild 2010-06-21 18:30:33

回答

12

如果您指定COUNT函數的列名稱,它不計算NULL值。

所以,簡單的方法是使用CASE語句,你不希望計數的值轉換爲NULL

SELECT 
    Name, 
    COUNT(CASE 
      WHEN Occurred_Date >= '2010-01-01' AND Occurred_Date < '2011-01-01' 
       THEN Occurred_Date 
      ELSE NULL 
      END) AS [YTD] 
    COUNT(CASE 
      WHEN Occurred_Date >= '2010-06-01' AND Occurred_Date < '2011-07-01' 
       THEN Occurred_Date 
      ELSE NULL 
      END) AS [MTD] 
FROM Table1 
GROUP BY Name 

我不是100%肯定的查詢引擎將讓你使用CASE內COUNT(我甚至不確定你使用的數據庫平臺),但它給了你這個想法。如果這種方式不起作用,您可以使用派生表編寫查詢,該表會給出相同的結果。

+0

糟糕,我沒有注意到您的「總計」是當月的計數。 我正在測試CASE是否可以在SQL服務器上使用COUNT。完成後,我會發布更完整的摘錄。 – Toby 2010-06-21 18:38:03

+2

如果你不想依賴Null行爲,你總是可以讓case語句返回1或0,然後做一個總和而不是一個計數。 – JohnFx 2010-06-21 18:38:07

+0

@JohnFx:是的,這也適用。根據表格定義,如果我知道我將處理大型集合,我有時會編寫並測試性能。 – Toby 2010-06-21 18:46:29

0

你或許可以使用MySQL的IF語句上的計數

1

看起來像一個聯盟的好情況。

SELECT Name, COUNT(Column1) AS Total, COUNT(Column1) AS YearToDate 
FROM Table1 
WHERE Occurred_Date BETWEEN '2010-06-01' AND '2010-06-30' --Total 
UNION 
SELECT Name, COUNT(Column1) AS Total, COUNT(Column1) AS YearToDate 
FROM Table1 
WHERE Occurred_Date BETWEEN '2010-01-01' AND '2010-06-30' --YearToDate 

基本上你是分別做兩個查詢,然後將它們組合成一個集合。

不確定你使用哪種類型的數據庫,但這裏有鏈接SQL ServerMySql

+0

恩,沒有。這導致了2行,實際上在大多數DB中都是錯誤的。需要按名稱分組... 之後,您將獲得兩行。一行將具有正確的值和YeartoDate的錯誤值,另一行將是相反的。當你知道你有兩個不同的結果集時,也不要使用UNION。 UNION強制排序,UNION ALL不行。是的,這只是兩排......這只是一個壞習慣。在需要完成額外工作時,始終使用UNION ALL並刪除ALL。 – 2010-06-21 19:33:19

1

您還可以使用

SELECT m.count, ytd.count FROM 
    (SELECT COUNT(id) count FROM table WHERE date BETWEEN BETWEEN '2010-06-01' AND '2010-06-30') m, 
    (SELECT COUNT(id) count FROM table WHERE date BETWEEN BETWEEN '2010-01-01' AND '2010-06-30') ytd 
0
SELECT COALESCE(CurrMonth.Name, YTD.Name) AS Name, CurrMonth.Total AS Total, YTD.Total AS YearToDate 
FROM (
    SELECT Name, COUNT(Column1) AS Total 
    FROM Table1 
    WHERE Occurred_Date BETWEEN '2010-06-01' AND '2010-06-30' --Total 
    GROUP BY Name 
) AS CurrMonth 
FULL OUTER JOIN 
(
    SELECT Name, COUNT(Column1) AS Total 
    FROM Table1 
    WHERE Occurred_Date BETWEEN '2010-01-01' AND '2010-06-30' --YearToDate 
    GROUP BY Name 
) AS YTD 
ON CurrMonth.Name = YTD.Name 

完全外部連接是沒有必要的,但只是演示瞭如何可能需要其中一組是不是其他的嚴格子集來辦案。我通常使用YTD子查詢LEFT JOIN到當前月份子查詢。

另一種策略 - 使用CASE:

SELECT Name 
    ,COUNT(CASE WHEN Occurred_Date BETWEEN '2010-06-01' AND '2010-06-30' THEN Column1 ELSE NULL END) AS Total 
    ,COUNT(CASE WHEN Occurred_Date BETWEEN '2010-01-01' AND '2010-06-30' THEN Column1 ELSE NULL END) AS YearToDate 
FROM Table1 
WHERE Occurred_Date BETWEEN '2010-06-01' AND '2010-06-30' -- (unnecessary) 
    OR Occurred_Date BETWEEN '2010-01-01' AND '2010-06-30' 
GROUP BY Name 
0
SELECT Name 
    ,SUM(
     CASE WHEN Occurred_Date BETWEEN '2010-06-01' AND '2010-06-30' 
     THEN 1 
     ELSE 0 
     END) AS Total 
    ,SUM(
     CASE WHEN Occurred_Date BETWEEN '2010-01-01' AND '2010-06-30' 
     THEN 1 
     ELSE 0 
     END) AS YearToDate 
FROM Table1 
GROUP BY Name 

編輯:這應該在SQL Server中工作。

0
SELECT DISTINCT m.field1, b.field2, 

      SUM (CASE 
        WHEN m.created_on >= 
             TO_DATE ('15/11/2012', 'DD/MM/YYYY') 
        AND m.created_on < 
            TO_DATE ('15/11/2012', 'DD/MM/YYYY') 
            + 1 
         THEN 1 
        ELSE 0 
       END 
       ) AS count1, 
      COUNT (1) AS count2 
     FROM table1 m, table2 b 
     WHERE m.field1 IN (SELECT DISTINCT field1 
            FROM table1) 
     AND b.field1 = m.field1 
    GROUP BY m.field1, b.field2 
    ORDER BY count2 DESC; 
+0

描述將有助於這個答案... – Craig 2012-12-21 07:00:19