使用嵌套SELECT保留SQL WHERE IN()子句的顺序

时间:2016-06-01 06:49:42

标签: mysql sql

我需要一个按项目数排序的项目名称列表。商品名称和相应的ID存储在tabletwo中,而tableone是指ID的商品:

      tableone              tabletwo
+--------+-----------+    +----+------+
| itemid | condition |    | id | name |
+--------+-----------+    +----+------+
| 2      | satisfied |    | 1  | foo  |
+--------+-----------+    +----+------+
| 1      | satisfied |    | 2  | bar  |
+--------+-----------+    +----+------+
| 3      | satisfied |    | 3  | hurr |
+--------+-----------+    +----+------+
| 3      | satisfied |    | 4  | durr |
+--------+-----------+    +----+------+
| 3      | satisfied |
+--------+-----------+
| 4      | satisfied |
+--------+-----------+
| 4      | satisfied |
+--------+-----------+
| 3      | nope      |
+--------+-----------+
| 1      | satisfied |
+--------+-----------+

SQL代码:

SELECT `itemname` FROM `tabletwo` WHERE `id` IN (
    SELECT `itemid` FROM (
        SELECT count(`itemid`), `itemid`
        FROM `tableone`
        WHERE `some_codition`="satisfied"
        GROUP BY `itemid`
        ORDER BY count(`itemid`) DESC
    ) alias
)

嵌套SELECT以后代顺序返回项ID的列表:3, 4, 1, 2。然后将此列表用作IN()子句的参数。 整个查询的预期结果是:hurr, durr, foo, bar(按照确切的顺序)。但订单不会保留。我知道它可以这样做:ORDER BY FIELD(id, 3, 4, 1, 2)但我不知道如何在我的情况下动态获取有序列表时如何做这个技巧。我需要再次SELECT吗?或临时表可能吗?或者在SQL之外构建另一个查询是否更好?

2 个答案:

答案 0 :(得分:3)

使用JOIN代替IN

SELECT
    t2.name
FROM tabletwo t2
LEFT JOIN tableone t1
    ON t1.itemid = t2.id
    AND t1.`condition` = 'satisfied'
GROUP BY
    t2.id, t2.name
ORDER BY COUNT(*) DESC

如果您要排除tabletwo上没有tableone匹配项的行,请使用INNER JOIN代替LEFT JOIN

ONLINE DEMO

答案 1 :(得分:3)

请尝试使用JOIN

SELECT t2.`itemname` 
FROM `tabletwo` AS t2
JOIN (    
   SELECT count(`itemid`) AS cnt, `itemid`
   FROM `tableone`
   WHERE `some_codition`="satisfied"
   GROUP BY `itemid`
) AS t1 ON t1.`itemid` = t2.`id`
ORDER BY t1.cnt DESC

您可以使用IN运算符的子查询创建派生表,并对此表执行JOIN,以便您可以使用{{1}中的COUNT主查询的子句。