仅从具有限制的优先排序组中选择一个元素?

lum*_*umo 2 mysql group-by

此问题在纯 sql 中搜索答案(无 db-server 特定代码)

-edit- 应有的评论/答案:“纯 sql”- SQL92/99 因为这适用于所有服务器。我不仅在 mysql 上使用此代码,这只是我尝试的第一个代码。我必须支持 Microsoft SQL Server (2000!)、h2、PostGRE SQL 和 MySQL Server,但代码也应该适用于其他人(独立于数据库服务器)。如果“纯sql”不够详细,我很抱歉。下次我会指定 SQL 修订的要求 (3/4, 92/99)

我必须向后兼容。这就是我没有指定数据库服务器的原因。这是故意的。-编辑结束-

我尝试从具有给定限制的表中获取所有值。我用于查询的数据是:可能的语言环境和一个 max_priority

这是要使用的表

SELECT * FROM i18n
Run Code Online (Sandbox Code Playgroud)

.

id|featureName|locale     |priority|text
--+-----------+-----------+--------+----
 1| type      |         en|       1|father
 2| type      |         de|       2|Vater
 3| type      |      de_AT|       3|Papa
 4| type      | de_AT_Wien|       4|Oida
 5| firstName |         en|       1|first name
 6| firstName |         de|       2|Vorname
 7| lastName  |         en|       1|last name
 8| lastName  |         de|       2|Nachname
 9| lastName  |         fr|       2|nom de famille
10| firstName |         fr|       2|prénom
Run Code Online (Sandbox Code Playgroud)

因此,例如我有en, de,de_AT和 3 的 max_priority(这是 的优先级de_AT)我希望这是结果:(这些结果的顺序并不重要!)

id|featureName|locale     |priority|text
--+-----------+-----------+--------+----
 3| type      |      de_AT|       3|Papa
 6| firstName |         de|       2|Vorname
 8| lastName  |         de|       2|Nachname
Run Code Online (Sandbox Code Playgroud)

我试图用left outer join 这是我能得到的最好结果来解决这个问题:

SELECT DISTINCT nls1.*
FROM i18n nls1
LEFT OUTER JOIN i18n nls2
ON (
    nls1.featureName = nls2.featureName
    and nls1.priority > nls2.priority
)
WHERE nls2.priority<=3
AND (nls1.locale='en' OR nls1.locale='de' OR nls1.locale='de_AT')
GROUP BY featureName
ORDER BY featureName, priority DESC
Run Code Online (Sandbox Code Playgroud)

但这会选择那些行:

id|featureName|locale     |priority|text
--+-----------+-----------+--------+----
 2| type      |         de|       2|Vater
 6| firstName |         de|       2|Vorname
 8| lastName  |         de|       2|Nachname
Run Code Online (Sandbox Code Playgroud)

另一个尝试是

SELECT nls2.* 
FROM   i18n nls2 
       JOIN (SELECT Max(priority) max_priority, 
                    featurename, 
                    priority 
             FROM   i18n nls 
             WHERE  ( locale = 'en' 
                       OR locale = 'de' 
                       OR locale = 'de_AT' ) 
                    AND priority <= 3 
             GROUP  BY featurename) nls3 
         ON nls3.priority = nls2.priority 
            AND nls3.featurename = nls2.featurename 
Run Code Online (Sandbox Code Playgroud)

但这一个只返回 en 版本......

id|featureName|locale     |priority|text
--+-----------+-----------+--------+----
 1| type      |         en|       1|father
 5| firstName |         en|       1|first name
 7| lastName  |         en|       1|last name
Run Code Online (Sandbox Code Playgroud)

注意:我会根据答案更新问题。

主要问题似乎是我需要一个group byancolumn但该组还需要一个order by?

ype*_*eᵀᴹ 5

如果没有窗口函数,查询会很复杂。MySQL中解决问题的一种方法:

SELECT 
    n.*
FROM 
    ( SELECT DISTINCT featureName
      FROM i18n
    ) AS d
  JOIN
    i18n AS n
  ON  n.id = 
      ( SELECT i.id
        FROM i18n AS i
        WHERE i.featureName = d.featureName
          AND i.locale IN ('en', 'de', 'de_AT')
          AND i.priority <= 3
        ORDER BY i.priority DESC
        LIMIT 1
      ) 
ORDER BY 
    n.featureName ;           -- or whatever you like, eg:  BY n.id
Run Code Online (Sandbox Code Playgroud)

另请注意,上面的查询在 SQL Server(使用TOP,not LIMIT)中将失败,并且在其他 DBMS 中也可能失败。