在 MySQL 子查询中尝试 select 唯一结果的问题

Issues trying to select unique results in MySQL sub query

必须编写一个 select 语句,其中 return 是位于唯一城市和州的每个供应商的名称、城市和州。我已经看到了几个类似的主题,但出于某种原因,none 给出的答案有所帮助。我的代码仍然无法 return 正确数量的结果:

Write a select statement that returns the name, city, and state of each vendor that's located in a unique city and state. It needs to return 38 rows.

/*problem 6*/

SELECT 
vendor_name, vendor_city, vendor_state
FROM
vendors
WHERE
vendor_city || vendor_state NOT IN (SELECT distinct
        vendor_city || vendor_state
    FROM
        vendors
    GROUP BY vendor_city, vendor_state having count(*)>1)
ORDER BY vendor_state , vendor_city;

此查询应满足规范的一种可能解释:

  SELECT MIN(v.vendor_name) AS vendor_name
       , v.vendor_city
       , v.vendor_state
    FROM vendors v
   GROUP
      BY v.vendor_city
       , v.vendor_state
  HAVING COUNT(*) = 1

这是获取 (city,state) 元组,并计算具有相同值的行数,并排除超过一行具有相同值的行数。在剩下的行中,只有 vendor_name 到 return.

(规范也可能有不同的解释,例如,多个 (city,state) 中的相同 vendor_name,我们希望 return 仅出现在一个中的 vendor_name单个 (city,state)。这需要不同的查询。)


MySQL 中的扩展允许我们放弃聚合函数,如果 ONLY_FULL_GROUP_BY 不包含在 sql_mode 中,即我们可以将 MIN(v.vendor_name) 替换为 v.vendor_name.

如果有一些要求我们必须使用嵌套查询,我更愿意使用内联视图而不是 return "unique city and state",然后是连接操作。

  SELECT t.vendor_name
       , t.vendor_city
       , t.vendor_state
    FROM ( SELECT v.vendor_city
                , v.vendor_state
             FROM vendors v
            GROUP
               BY v.vendor_city
                , v.vendor_state
           HAVING COUNT(*) = 1
         ) u
    JOIN vendors t
      ON t.vendor_city  <=> u.vendor_city
     AND t.vendor_state <=> u.vendor_state 
   ORDER
      BY t.vendor_name

寻求正面回应通常效率更高。因此,与其查找那些拥有超过 city/state 的供应商(然后使用 NOT 来反转它),不如预先进行反向操作,只寻找那些拥有单个 city/state 的供应商。然后使用 inner join.

对最终输出使用更直接的方法
SELECT
      v.vendor_name
    , v.vendor_city
    , v.vendor_state
FROM vendors AS v
INNER JOIN (
      SELECT
            vendor_city
          , vendor_state
      FROM vendors
      GROUP BY
            vendor_city
          , vendor_state
      HAVING COUNT(*) = 1
) AS d ON v.vendor_city = d.vendor_city
      AND v.vendor_state = d.vendor_state
ORDER BY v.vendor_state, v.vendor_city;