【问题标题】:What's wrong with this SQL?这个 SQL 有什么问题?
【发布时间】:2016-06-28 02:20:25
【问题描述】:

这是 SQL Server:

SQL:

SELECT 
    Tb_Supplier.State, Tb_Supplier.City,
    COUNT(DISTINCT Tb_Supplier.Name) as Suppliers
    Tb_Consumer.State, Tb_Consumer.City,
    COUNT(DISTINCT Tb_Consumer.Name) as Consumers

【问题讨论】:

  • 这适用于哪个 RDBMS?请添加标签以指定您使用的是mysqlpostgresqlsql-serveroracle 还是db2 - 或其他完全不同的东西。
  • Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSI JOIN 语法-92 SQL 标准(20 多年前),不鼓励使用它
  • 您为什么使用低效的交叉联接(笛卡尔积)而不是内部联接?返回什么错误?
  • 内部联接在这里不起作用,因为他需要两者的计数(在某些情况下它可能为零。但如果使用 RDBMS 支持,完整的外部联接可能会起作用。我不确定期望的输出应该是什么样子。它可能只是州、城市、供应商计数、消费者计数。
  • 我已经标记了问题sql-servertsql(我假设“msql”是“mssql”)请在以后的问题中使用这些标签

标签: sql sql-server tsql


【解决方案1】:
SELECT
      COALESCE(s.state, c.state) AS state
    , COALESCE(s.city, c.city) AS city
    , COALESCE(s.Suppliers, 0) AS Suppliers
    , COALESCE(c.Consumers, 0) AS Consumers
FROM (
      SELECT
            Tb_Supplier.State
          , Tb_Supplier.City
          , COUNT(Tb_Supplier.Name) AS Suppliers
      FROM Tb_Supplier
      GROUP BY
            Tb_Supplier.City
          , Tb_Supplier.State
) AS s
      FULL OUTER JOIN (
            SELECT
                  Tb_Consumer.State
                , Tb_Consumer.City
                , COUNT(Tb_Consumer.Name) AS Consumers
            FROM Tb_Consumer
            GROUP BY
                  Tb_Consumer.City
                , Tb_Consumer.State
      ) AS c ON s.state = c.state
                  AND s.city = c.city

上面的查询使用我假设的供应商和消费者的“主表”,因此每个行中的行应该唯一地定义一个供应商或消费者。因此,上述方法不需要count(distinct...)。使用full outer join 是因为在州/市可能存在没有匹配消费者的供应商,反之亦然。因此,coalesce 在最终的 select 子句中用于处理可能来自供应商或消费者端的 NULL。

为什么不应该在表格之间使用逗号:

-- Accidental Cross Join? (Cartesian Product)
-- or is it Deliberate
select * from table_one, table_two

在上面的示例中,table_one 的 每一行 乘以 table_two 的所有行。因此,如果两个表都有 100 行,则结果为 100*100 = 10,000 行。我想要 10,000 行吗?

你不知道我是否想要,这可能是故意的,也可能只是意外。

select * from table_one CROSS JOIN table_two

但现在我知道交叉连接是故意的。

回头看看你原来的问题。

FROM 
    Tb_Supplier, Tb_Consumer
GROUP BY 
    Tb_Supplier.City, Tb_Supplier.State, Tb_Consumer.City, Tb_Consumer.State​

如果您有 1,000 个供应商和 100,000 个消费者,您在 from 子句中创建了多少行? (1,000 * 100,000 = 100,000,000) 我很确定这是偶然的,这就是为什么你应该停止在 from 子句中的表之间使用逗号。

【讨论】:

  • @dedpo 您试图编辑我的评论,但该编辑已被拒绝。你想做什么?你需要什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 2013-10-13
  • 2010-10-21
  • 2012-07-07
  • 2012-05-02
  • 1970-01-01
相关资源
最近更新 更多