【问题标题】:SQL: Can I refer/access data the current row in a window function?SQL:我可以在窗口函数中引用/访问当前行的数据吗?
【发布时间】:2018-03-23 11:49:36
【问题描述】:

这是一个例子。假设我有下表:

 id     | list
--------+----------
 10     |
        | 10,20
 20     | 10,20

对于每个 id 值,我想计算包含 id 值的 list 值的行数。结果应该是这样的:

 id     | count of lists
--------+----------
 10     | 2
        | 0
 20     | 2

我建议应该使用窗口函数,但我似乎无法从这样的函数中访问id 值。

我完全同意这是糟糕的设计。这个问题是关于可能性的。

任何 MySQL/PostgreSQL 解决方案都可以。

【问题讨论】:

  • 不知道你想问什么。 ID 10 有一个空白,但空白有 0 个计数?空白 ID 也有点奇怪。它们是列表中值的上限吗?这里的设计很糟糕
  • 这看起来真的很糟糕的表格设计...对于两列...为什么您要查找的值作为包含列表值的表格中的单独列?为什么要在数据库中存储逗号分隔的值?想想如果您在列表中有100 并且您正在寻找10 会发生什么。这将需要一个过于复杂的解决方案来解决如果设计经过深思熟虑就可以轻松完成的事情。
  • Mysql 还是 postgres??
  • 请正确标记。 mysql还是postgres?不能两者兼而有之。
  • 在我看来,您想从逗号分隔列表中计算出数字吗?

标签: mysql sql postgresql


【解决方案1】:

假设您使用的是 MySQL,并假设您的表的名称为 test,并假设两列都是字符串类型:

SELECT
  t1.id, count(t2.list)
FROM
(test t1 LEFT JOIN test t2 ON
  (t2.list LIKE CONCAT('%,', t1.id, ',%')) OR
  (t2.list LIKE CONCAT('%,', t1.id)) OR
  (t2.list LIKE CONCAT(t1.id, ',%')))
GROUP BY t1.id;

请注意,此解决方案可能会非常慢,具体取决于您拥有的记录数量以及list 字段中字符串的平均长度。

如果您需要更快的东西,我认为它不可能是单个查询。也许我们必须为此编写一个存储过程或一些应用程序逻辑,或者使用额外的表或列以及一系列多条 SQL 语句。

【讨论】:

    【解决方案2】:

    在我开始之前,如上所述,这是一个糟糕的设计。但是,这就是我查询它的方式:

    CREATE TABLE #Lists (id int, list varchar(500));
    INSERT INTO #Lists (id, list) VALUES
        (10, NULL), (NULL, '10,20'), (20, '10,20');
    
    WITH cte AS (
        SELECT LEFT(list, INSTR(list, '%,%')-1) AS value, SUBSTRING(list, INSTR(list, '%,%') + 1, 500) AS list FROM #Lists
        UNION ALL
        SELECT CASE WHEN list LIKE ('%,%') THEN LEFT(list, INSTR(list, '%,%')-1) ELSE list END AS value, CASE WHEN list LIKE ('%,%') THEN SUBSTRING(list, INSTR(list, '%,%') + 1, 500) END AS list FROM cte 
        WHERE CHAR_LENGTH(list) > 0
    )
    
    SELECT value, COUNT(*) FROM cte GROUP BY value;
    
    DROP TABLE #Lists;
    

    此解决方案允许list 字符串中包含任意数量的值(例如“10,20,30”)。

    理想情况下,列表值应存储在单独的表中,以便每条记录都有一个值,例如CREATE TABLE BetterDesign (id int, value int) INSERT INTO BetterDesign (id, value) VALUES (10, NULL), (NULL, 10), (NULL, 20), (20, 10), (20, 20)。连同其他一百万个原因,这更适合查询SELECT value, COUNT(*) FROM BetterDesign GROUP BY value。话虽如此,我理解遗留系统的痛苦。

    【讨论】:

      猜你喜欢
      • 2017-08-14
      • 2017-03-28
      • 2015-10-02
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 2018-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多