【问题标题】:SQL query that finds the an id that is not associated with another id查找未与另一个 id 关联的 id 的 SQL 查询
【发布时间】:2020-03-07 04:41:52
【问题描述】:

我目前正在学习 SQL 的基本知识,并且我有一个来自学校的教程,内容如下: 所有商店(storeid) 销售(productid, storeid) 部分产品(productid) 如果一家商店销售的所有产品都没有被任何其他商店出售,则该商店被视为垄断。 如何找到垄断? 我正在考虑从 2 个相同的表中选择 storeid,但我不确定如何从那里继续。

表格如下:

商店:

+-----------+
|  storeid  |
+-----------+
| --------- |
|     1     |
|     2     |
|     3     |
|     4     |
|     5     |
+-----------+

产品:

+-------------+
|  productid  |
+-------------+
| ---------   |
|     1       |
|     2       |
|     3       |
|     4       |
|     5       |
|     6       |
+-------------+

卖出:

+--------------------------+
|   productid | storeid    |
+--------------------------+
| -----------+------------ |
|          1 |          1  |
|          2 |          1  |
|          2 |          2  |
|          3 |          2  |
|          1 |          2  |
|          3 |          3  |
|          2 |          4  |
|          4 |          4  |
|          5 |          5  |
|          6 |          5  |
+--------------------------+

所以根据我的统计,只有 5 号商店被认为是垄断的,因为他们销售的产品是其他商店没有的。

【问题讨论】:

    标签: mysql sql postgresql


    【解决方案1】:

    我们可以尝试结合聚合的自连接方法:

    SELECT t1.storeid
    FROM yourTable t1
    LEFT JOIN yourTable t2
        ON t2.productid = t1.productid AND
           t2.store_id <> t1.storeid
    GROUP BY t1.storeid
    HAVING COUNT(t2.storeid) = 0;
    

    这里的方法是尝试将Sells 中的每一行与其他行匹配,条件是它是相同的产品,但正在由其他商店出售。匹配的商店是其产品没有被其他商店出售的商店,因此连接中第二个表列的计数应该为零。

    【讨论】:

    • 哦,成功了!没想过用“AND t2.store_id t1.storeid”,是不是可以有多少只要能得到你想要的?
    • 类似:LEFT JOIN ON .... AND ... AND ... etc. 可以有任意数量的条件?
    • 也许吧。这取决于要解决的问题。随时问另一个问题。
    【解决方案2】:

    使用窗口函数和聚合:

    select s.storeid
    from (select s.*,
                 count(*) over (partition by productid) as num_stores
          from sells s
         ) s
    group by s.storeid
    having max(num_stores) = 1;
    

    这应该比自加入快得多。它也几乎是您问题的直接翻译。子查询计算销售每种产品的商店数量。外部查询选择在一个商店中销售所有产品的商店。

    【讨论】:

    • 这个答案假设 OP 的数据库是 Postgres 或 MySQL 8+。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 2016-08-07
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多