SQL:排序依据、子字符串、联合

SQL: Order By, Substring, Union

我希望按 'version' 数字的前 8 个字符的子字符串对以下查询的结果进行排序。我理解 SUBSTRING(),所以不要用这个来打扰我。我的问题是尝试实际放置关于 UNION 的 ORDER BY。

更新:我需要按版本顺序返回的数据,但仍然排在具有相同 GUID 的其他行的旁边。

当前查询是这样的,但是版本是随机的。

/**** PLAYER MATCHUPS TWO  ***/    
SELECT e.[GUID], e.[KEY], e.[VALUE]    
FROM db e INNER JOIN 
    (SELECT[GUID] FROM db
    WHERE[Key] = 'Session.Type' and[Value] = 'EndMatchTypA') g 
ON e.[GUID] = g.[GUID] 
WHERE [KEY] IN('CharacterID', 
            'OpponentID', 
            'Version')
UNION ALL

/**** PLAYER MATCHUPS ONE  ***/
SELECT e.[GUID], e.[KEY], e.[VALUE] 
FROM db e INNER JOIN 
    (SELECT[GUID] FROM db
    WHERE[Key] = 'Session.Type' and [Value] = 'EndMatchTypeB') g 
ON e.[GUID] = g.[GUID] 
WHERE[KEY] IN('CharacterID', 
        'OpponentID',
        'Version')

目前returns的数据是这样的。

GUID        Key             Value
-------------------------------------------
1313-2212   Version         3.0.4.0_x64_!#
1313-2212   CharacterID     3
1313-2212   OpponentID      5
4321-1567   Version         1.0.0.0_x64_!#
4321-1567   CharacterID     11
4321-1567   OpponentID      2

您可以包装整个查询,然后 SELECT 使用 ORDER BY:

SELECT t.[GUID], t.[KEY], t.[VALUE]
FROM
(
    SELECT e.[GUID], e.[KEY], e.[VALUE]    
    FROM db e INNER JOIN 
        (SELECT[GUID] FROM db
        WHERE[Key] = 'Session.Type' and[Value] = 'EndMatchTypA') g 
    ON e.[GUID] = g.[GUID] 
    WHERE [KEY] IN('CharacterID', 
                'OpponentID', 
                'appVer')
    UNION ALL
    SELECT e.[GUID], e.[KEY], e.[VALUE] 
    FROM db e INNER JOIN 
        (SELECT[GUID] FROM db
        WHERE[Key] = 'Session.Type' and [Value] = 'EndMatchTypeB') g 
    ON e.[GUID] = g.[GUID] 
    WHERE[KEY] IN('CharacterID', 
            'OpponentID',
            'appVer')
) t
ORDER BY SUBSTRING(t.[VALUE], 1, 8)

注意:我测试了对字符串版本号的排序,数字顺序似乎保持不变。但是,您应该知道,如果您的版本号长度发生变化,这可能是个问题。例如,如果版本可以变成两位数,这将打破我给出的 ORDER BY(以及其他答案给出的)。

查询可以简化如下。使用 substring 获取 value 的前 8 个字符,并将 . 字符替换为空字符,以便它可以作为整数排序。

SELECT e.[GUID], e.[KEY], e.[VALUE] 
FROM db e 
INNER JOIN 
(SELECT[GUID] FROM db
 WHERE [Key] = 'Session.Type' and [Value] = 'EndMatchTypeA') ga
ON e.[GUID] = ga.[GUID] 
INNER JOIN 
(SELECT[GUID] FROM db
 WHERE [Key] = 'Session.Type' and [Value] = 'EndMatchTypeB') gb
ON e.[GUID] = gb.[GUID] 
WHERE e.[KEY] IN ('CharacterID','OpponentID','appVer')
ORDER BY cast(replace(substring(e.[VALUE],1,8),'.','') as int)

如果要将 order byunion 一起使用,请在 union 查询末尾使用 order by

select col1,col2 from sometable --where conditions
union all
select col1,col2 from sometable1 --where conditions
order by col1,col2

首先,我不明白你为什么需要 union all:

SELECT e.[GUID], e.[KEY], e.[VALUE] 
FROM db e INNER JOIN
     db g 
     ON e.[GUID] = g.[GUID] AND 
        g.[Key] = 'Session.Type' AND
        g.[Value] IN ('EndMatchTypeA', 'EndMatchTypeB') 
WHERE e.[KEY] IN ('CharacterID', 'OpponentID', 'Version')
ORDER BY SUBSTRING(e.[VALUE], 1, 8);

然后,我可能会将其更改为 EXISTS:

SELECT e.[GUID], e.[KEY], e.[VALUE] 
FROM db e 
WHERE e.[KEY] IN ('CharacterID', 'OpponentID', 'Version') AND
      EXISTS (SELECT 1
              FROM db g 
              WHERE e.[GUID] = g.[GUID] AND 
                    g.[Key] = 'Session.Type' AND
                    g.[Value] IN ('EndMatchTypeA', 'EndMatchTypeB')
             )
ORDER BY SUBSTRING(e.[VALUE], 1, 8);

我认为这最能表达查询的意图。而且,它可以防止 can g 中的重复项具有两个值。而且,它可能使优化器更容易利用适当的索引。

您需要对 db table 执行另一个 JOIN 以获得每个 [KEY] 排序的 Version

SELECT 
    e.[GUID], e.[KEY], e.[VALUE] 
FROM db e 
INNER JOIN db g 
    ON  e.[GUID] = g.[GUID] 
        AND g.[Key] = 'Session.Type'
        AND g.[Value] IN ('EndMatchTypeA', 'EndMatchTypeB')
INNER JOIN (
    SELECT [GUID], [KEY], [VALUE]
    FROM db
    WHERE
        [KEY] = 'Version'
)v
    ON e.[GUID] = v.[GUID]
WHERE 
    e.[KEY] IN ('CharacterID', 'OpponentID', 'Version')
ORDER BY 
    SUBSTRING(v.[VALUE], 1, 8);

您也可以使用CROSS APPLY

SELECT 
    e.[GUID], e.[KEY], e.[VALUE] 
FROM db e 
INNER JOIN db g 
    ON  e.[GUID] = g.[GUID] 
        AND g.[Key] = 'Session.Type'
        AND g.[Value] IN ('EndMatchTypeA', 'EndMatchTypeB')
CROSS APPLY (
    SELECT [GUID], [KEY], [VALUE]
    FROM db
    WHERE
        [KEY] = 'Version'
        AND [GUID] = e.[GUID]
)v
WHERE 
    e.[KEY] IN ('CharacterID', 'OpponentID', 'Version')
ORDER BY 
    SUBSTRING(v.[VALUE], 1, 8);

感谢 Gordon 摆脱了 UNION ALL