MySQL选择默认是最后的手段
Posted
技术标签:
【中文标题】MySQL选择默认是最后的手段【英文标题】:MySQL Select where default is last resort 【发布时间】:2021-09-01 06:08:05 【问题描述】:我正在尝试获取一个连接表,同时按一列排序并分组。我正在尝试选择以 CU 开头的 CUID,而不是 DEFAULT 值。我已经阅读了 *** 上发布的答案,看来我做的事情是正确的。我认为这可能只是我缺少的一些小东西。我认为由于插入顺序,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”之后,这仅在某些时候有效。
表 A
| id | Name |
| 1 | blah |
| 2 | was |
| 3 | here |
表 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 |
【问题讨论】:
查询不正确。请参阅 ONLY_FULL_GROUP_BY sql 模式说明。 @Akina 这个查询对我来说很好。 查询对我来说很好用。“很好用”和“给出意外结果”不兼容。关于查询。您的数据中有Value
值 'a'
和 'c'
对应于 SettingID=1
。分组后服务器必须返回一个值。您尚未指定必须返回的内容(first-last-greatest-least-etc.)。服务器从他们那里随机返回一个 - 这对它来说是正确的。没有明确描述的任何东西都可以是任何东西。你需要一些确定的价值吗?如果是这样,那么您的查询不符合您的需要 - 即它不正确。
@akina 抱歉,我更新了我的问题,使其更具体。该表可以有一个 DEFAULT 设置和任何其他 CUID 设置。只会有另一个。存在 DEFAULT 且 CUID = BLAH 时的示例。我想用 BLAH 抢排。我希望 DEFAULT 成为次要选项。
【参考方案1】:
您可以使用EXISTS
执行此操作,这样对于每个SettingID
,您将获得以CUID
开头的行,以'CU'
开头,或者如果它不存在,那么您将获得具有替代值的行:
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+,你可以使用TableB
表中的ROW_NUMBER()
窗口函数来获取首选行:
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。
【讨论】:
这正是我想要的。我需要做的就是将“CU%”更改为我正在寻找的实际值。谢谢。【参考方案2】:该表可以有一个 DEFAULT 设置和任何其他 CUID 设置。只会有另一个。
我会使用
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
。
【讨论】:
这并没有给我任何默认值。结果只是设置ID 1和2 @SariRahal 哎呀……对不起。固定。以上是关于MySQL选择默认是最后的手段的主要内容,如果未能解决你的问题,请参考以下文章