MySQL Select 默认是最后的手段

MySQL Select where default is last resort

我正在尝试加入 table 并按一列和分组进行排序。我正在尝试 select 以 CU 开头的 CUID 超过 DEFAULT 值。我已经阅读了 Whosebug 上发布的答案,看起来我做的事情是正确的。我认为这可能只是我缺少的一些小东西。我认为由于插入顺序,order by 不起作用。我想查询使用 DEFAULT 作为最后一个选项。

SELECT A.*, B.value, B.CUID  
FROM A 
JOIN B 
ON A.ID = B.SettingID 
WHERE B.CUID = 'CU1' OR B.CUID = 'DEFAULT'
GROUP BY ID
ORDER BY CUID ASC 

在朋友的帮助下,发现这只在某些时候有效,因为插入顺序,并且只有 B.CUID 按字母顺序排列在 'DEFAULT' 之后。

Table一个

| id   | Name  | 
|  1   |  blah |
|  2   |  was  | 
|  3   |  here | 

Table B

| ID   | SettingID | Value | CUID    |
|  1   |  1        |  a    | CU1     |
|  2   |  2        |  b    | CU1     |
|  3   |  1        |  c    | DEFAULT |
|  4   |  2        |  d    | DEFAULT |
|  5   |  3        |  e    | DEFAULT |

没有 GROUP BY 的结果

|  SettingID | Name | Value | CUID    |
|    1       | blah |  a    | CU1     |
|    2       | was  |  b    | CU1     |
|    1       | blah |  c    | DEFAULT |
|    2       | was  |  d    | DEFAULT |
|    3       | here |  e    | DEFAULT |

GROUP BY

后的结果
|  SettingID | Name | Value | CUID    |
|    1       | blah |  c    | DEFAULT |
|    2       | was  |  d    | DEFAULT |
|    3       | here |  e    | DEFAULT |

预期结果

|  SettingID | Name | Value | CUID    |
|    1       | blah |  a    | CU1     |
|    2       | was  |  b    | CU1     |
|    3       | here |  e    | DEFAULT |

你可以用 EXISTS 来做,这样对于每个 SettingID 你都会得到以 'CU' 开头的 CUID 的行,或者如果它不存在那么您得到具有替代值的行:

SELECT a.*, b.value, b.CUID 
FROM TableA a 
INNER JOIN (
  SELECT b1.*
  FROM TableB b1
  WHERE b1.CUID LIKE 'CU%'
     OR NOT EXISTS (
       SELECT 1
       FROM TableB b2
       WHERE b2.SettingID = b1.SettingID AND b2.CUID LIKE 'CU%'
     )
) b ON b.SettingID = a.id

如果你的MySql版本是8.0+,你可以在tableTableB中使用ROW_NUMBER()window函数获取首选行:

SELECT a.*, b.value, b.CUID 
FROM TableA a 
INNER JOIN (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY SettingID ORDER BY CUID LIKE 'CU%' DESC) rn
  FROM TableB
) b ON b.SettingID = a.id
WHERE b.rn = 1

参见demo

The table can have a DEFAULT setting and any other CUID Setting. There will only be one other.

我会用

SELECT b1.SettingID, 
       a.name,
       COALESCE(b2.value, b1.value) AS value,
       COALESCE(b2.CUID, b1.CUID) AS CUID
FROM a
JOIN b AS b1 on a.id = b1.SettingID
LEFT JOIN b AS b2 ON a.id = b2.SettingID 
                 AND b2.CUID != 'DEFAULT'
WHERE b1.CUID = 'DEFAULT'  

如果每个 SettingID 可能有多个 'DEFAULT',则添加 DISTINCT