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 by
与 union
一起使用,请在 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
。
我希望按 '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 by
与 union
一起使用,请在 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
。