我需要一个特定的输出

时间:2014-02-27 13:37:15

标签: sql sql-server tsql

我必须从表格中获取特定的输出格式。

假设我有一个包含2列名称的简单表格。

T1

+---------------+------------------+
| Name          | Value            |
+---------------+------------------+
| stuff1        | 1                |
| stuff1        | 1                |
| stuff2        | 2                |
| stuff3        | 1                |
| stuff2        | 4                |
| stuff2        | 2                |
| stuff3        | 4                | 
+---------------+------------------+

我知道值在1-4区间。我按名称和值对其进行分组,并计算与数字相同的行数,并获取下表:

T2

+---------------+------------------+--------+
| Name          | Value            | Number |
+---------------+------------------+--------+
| stuff1        | 1                | 2      |
| stuff2        | 2                | 2      |
| stuff3        | 1                | 1      |
| stuff3        | 4                | 1      |
+---------------+------------------+--------+

这是我需要你帮助的部分!如果我想获得这些格式,我该怎么办?

T3

+---------------+------------------+--------+
| Name          | Value            | Number |
+---------------+------------------+--------+
| stuff1        | 1                | 2      |
| stuff1        | 2                | 0      |
| stuff1        | 3                | 0      |
| stuff1        | 4                | 0      |
| stuff2        | 1                | 0      |
| stuff2        | 2                | 2      |
| stuff2        | 3                | 0      |
| stuff2        | 4                | 0      |
| stuff3        | 1                | 1      |
| stuff3        | 2                | 0      |
| stuff3        | 3                | 0      |
| stuff3        | 4                | 1      |
+---------------+------------------+--------+

感谢您的任何建议!

3 个答案:

答案 0 :(得分:3)

您从cross join开始生成所有可能的组合,然后左键加入现有查询的结果:

select n.name, v.value, coalesce(nv.cnt, 0) as "Number"
from (select distinct name from table t) n cross join
     (select distinct value from table t) v left outer join
     (select name, value, count(*) as cnt
      from table t
      group by name, value
     ) nv
     on nv.name = n.name and nv.value = v.value;

答案 1 :(得分:2)

主题的变化。

Gordon Linoff和Owen现有答案之间的差异。

  1. 我更喜欢GROUP BY来获取名称而不是DISTINCT。在这种情况下,这可能具有更好的性能。 (见Rob Farley's still relevant article。)
  2. 为了清楚起见,我将子查询分解为一系列CTE。
  3. 我使用表T2作为问题现在标记组结果集而不是显示为子查询。

    WITH PossibleValue AS (
      SELECT 1 Value 
       UNION ALL
      SELECT Value + 1 
    FROM PossibleValue 
       WHERE Value < 4 
    ), 
    Name AS (
      SELECT Name 
        FROM T1
       GROUP BY Name
    ),
    NameValue AS (
      SELECT Name 
            ,Value
        FROM Name
             CROSS JOIN
             PossibleValue
    )
    SELECT nv.Name
          ,nv.Value
          ,ISNULL(T2.Number,0) Number
      FROM NameValue nv
           LEFT JOIN
           T2 ON nv.Name = T2.Name
             AND nv.Value = T2.Value
    

答案 2 :(得分:1)

另一种解决方案,这次使用CTE中的表值构造函数来构建名称值组合表。

WITH value AS 
( SELECT DISTINCT t.name, v.value
    FROM T1 AS t
   CROSS JOIN (VALUES (1),(2),(3),(4)) AS v (value)
)
  SELECT v.name AS 'Name', v.value AS 'Value', COUNT(t.name) AS 'Number'
    FROM value AS v
    LEFT JOIN T1 AS t ON t.value = v.value AND t.name = v.name
GROUP BY v.name, v.value, t.name;