【问题标题】:How to display output like this in SQL?如何在 SQL 中显示这样的输出?
【发布时间】:2017-08-23 07:17:18
【问题描述】:

我有一张如下所示的表格:

+----------------+-------+----------+---------+
| Name           | Model | system   | ItemTag |
+----------------+-------+----------+---------+
| Alarm Id       | T58   | ASC      |         |
+----------------+-------+----------+---------+
| Door Lock      | F48   | ASC      |         |
+----------------+-------+----------+---------+
| AlarmSounder   | T58   | ASC      |         |
+----------------+-------+----------+---------+
| Card Reader    | K12   | ASC      |         |
+----------------+-------+----------+---------+
| Magnetic Lock  | F48   | ASC      |         |
+----------------+-------+----------+---------+
| T2 Card Reader | K12   | ASC      |         |
+----------------+-------+----------+---------+
| Power   Supply | Null  | ASC      |         |
+----------------+-------+----------+---------+
| Battery         |  Null| ASC      |         |
+----------------+-------+----------+---------+

现在我想这样显示数据:

+-------------+-------+--------+--------+
| Name        | Model | system | count  |
+-------------+-------+--------+--------+
| Alarm       | T58   | ASC    | 2      |
+-------------+-------+--------+--------+
| Door Lock   | F58   | ASC    | 2      |
+-------------+-------+--------+--------+
| Card Reader | K12   | ASC    | 2      |
+-------------+-------+--------+--------+
|Power supply | Null   | ASC    | 1     |
+-------------+-------+--------+--------+
| Battery    | Null   | ASC    | 1     |
+-------------+-------+--------+--------+

如何在 SQL 中做到这一点?

更新 我还包括空列作为我的第二次更新。

【问题讨论】:

  • 这是什么逻辑?为什么AlarmSounderMagnetic LockT2 Card Reader 不在输出中?
  • @ZoharPeled ,更新了问题
  • 仍然没有帮助。如何区分要返回的行和不想返回的行?
  • 为什么 ('Alarm Id' , 'AlarmSounder') => 'Alarm' 但是 ('Door Lock', 'Magnetic Lock') => 'Door Lock' ?
  • @Serg ,这是我们的采购团队提供的,他们存储了这样的数据

标签: sql count group-by sql-server-2014 tabular


【解决方案1】:

您可以使用窗口函数:

SELECT Name, Model, system, cnt AS count 
FROM (SELECT *, COUNT(*) OVER(PARTITION BY Model) AS cnt,
            ROW_NUMBER() OVER(PARTITION BY Model ORDER BY ...) AS rn
      FROM your_tab) AS sub
WHERE rn = 1;

Rextester Demo

请记住,您需要一列进行排序,因此 (id/timestamp) 应该用于获取组中的第一个值。


编辑:

因为我有与空列相关的不同名称。我怎样才能把它分开

SELECT Name, Model, system, cnt AS count 
FROM (SELECT *, COUNT(*) OVER(PARTITION BY Model) AS cnt,
            ROW_NUMBER() OVER(PARTITION BY Model ORDER BY id) AS rn
      FROM my_tab
      WHERE Model IS NOT NULL) AS sub
WHERE rn = 1
UNION ALL
SELECT Name, Model, system, 1
FROM my_tab
WHERE Model IS NULL;

RextesterDemo 2

【讨论】:

  • 这几乎是完美的。所有行都以总数返回但我在空列中有问题。因为我有与空列相关的不同名称。我怎样才能把它分开
  • @aryan 现在您正在扩展您的问题。我建议用样本数据和结果提出新问题。您可以使用我的rextester.com 提供所有必要的数据。
  • @aryan:您需要包括所有有问题的场景,因为我们尝试根据提供的数据构建查询。您的示例数据中没有空值。
  • @lad2025 ,更新
【解决方案2】:

你可以有一个简单的查询如下

SELECT MIN(Name) Name, 
       Model, 
       system, 
       COUNT(*) [count]
  FROM yourtable
 GROUP BY Model, system

结果

Name        Model   system  count
Door Lock   F58     ASC     2
Card Reader K12     ASC     2
Alarm Id    T58     ASC     2

【讨论】:

    【解决方案3】:

    lad2025 的解决方案简化,一步计算 NULL 和 NOT NULL 并为 NULL 行添加一些逻辑:

    SELECT Name, Model, system, 
       CASE WHEN Model IS NULL THEN 1 ELSE cnt END AS count 
    FROM
     (
       SELECT *, 
          COUNT(*) OVER(PARTITION BY Model) AS cnt,
          ROW_NUMBER() OVER(PARTITION BY Model ORDER BY Name) AS rn
       FROM my_tab
     ) AS sub
    WHERE rn = 1         -- one row per model 
       OR Model IS NULL; -- all rows for the NULL model
    

    【讨论】:

    • 我没有得到case语句部分..0CASE WHEN Model IS NULL THEN 1 它说当模型为null然后1,它指向这里。
    • @aryan:这只是将 NULL 行的计数替换为 1 以匹配您的预期结果:-)
    • 是的。我用 not null 替换了 case 并查看了它在查询中实际执行的操作。谢谢你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多