SELECT
使用せずに、列に特定のデータを持つ行のみを作成する方法はありWHERE
ますか?
たとえば、これがあった場合:
SELECT * FROM Users
WHERE town = 'Townsville'
文にWHERE
句を実装する方法はありSELECT
ますか?
何かのようなもの
SELECT *, town('Townsville') FROM Users
奇妙な質問ですが、仲間から尋ねられた質問です
SELECT
使用せずに、列に特定のデータを持つ行のみを作成する方法はありWHERE
ますか?
たとえば、これがあった場合:
SELECT * FROM Users
WHERE town = 'Townsville'
文にWHERE
句を実装する方法はありSELECT
ますか?
何かのようなもの
SELECT *, town('Townsville') FROM Users
奇妙な質問ですが、仲間から尋ねられた質問です
回答:
これがあなたが探していた種類のクレイジーなものであるかどうかはわかりません....
免責事項:私はあなたがこれを使用したいと思う理由が全くわかりません。
SELECT *
FROM Users AS u
INNER JOIN (SELECT 'Townsville' town) towns
ON towns.town = u.Town;
DECLARE @Example AS table
(
UserName varchar(30) NULL,
Town varchar(30) NULL
);
INSERT @Example
(UserName, Town)
VALUES
('Aaron', 'Not Townsville'),
('Bob', 'Not Townsville'),
('Charles', 'Townsville'),
('Charles', 'Townsville'),
('Charles', 'Townsville'),
('Charles', 'Townsville'),
('Dan', 'Townsville'),
('Eric', 'Not Townsville');
SELECT E.UserName, E.Town
FROM @Example AS E
GROUP BY E.Town, E.UserName
HAVING E.Town = 'Townsville'
-- OR
SELECT E.UserName, 'Townsville' AS Town
FROM @Example AS E
GROUP BY E.UserName
HAVING 1 = MAX(CASE WHEN E.Town = 'Townsville' THEN 1 ELSE 0 END);
-- OR
SELECT E.UserName, E.Town
FROM @Example AS E
INTERSECT
SELECT E.UserName, 'Townsville' AS Town
FROM @Example AS E
-- :)
SELECT E.UserName, E.Town
FROM @Example AS E
CROSS APPLY (VALUES(NEWID())) AS CA (n)
GROUP BY E.Town, E.UserName, CA.n
HAVING E.Town = 'Townsville'
-- Simulating INTERSECT ALL
SELECT
R.UserName,
R.Town
FROM
(
SELECT
E.UserName,
E.Town,
rn =
ROW_NUMBER() OVER (
PARTITION BY E.UserName, E.Town
ORDER BY E.UserName, E.Town)
FROM @Example AS E
INTERSECT
SELECT
E.UserName,
'Townsville',
rn =
ROW_NUMBER() OVER (
PARTITION BY E.UserName
ORDER BY E.UserName)
FROM @Example AS E
) AS R;
出力:
╔══════════╦════════════╗
║ UserName ║ Town ║
╠══════════╬════════════╣
║ Charles ║ Townsville ║
║ Dan ║ Townsville ║
╚══════════╩════════════╝
最後の例:
╔══════════╦════════════╗
║ UserName ║ Town ║
╠══════════╬════════════╣
║ Charles ║ Townsville ║
║ Charles ║ Townsville ║
║ Charles ║ Townsville ║
║ Charles ║ Townsville ║
║ Dan ║ Townsville ║
╚══════════╩════════════╝
ここで試してください: Stack Exchange Data Explorer
GROUP BY
のソリューション、あなたはまた、(クエリが同じ行数を返すようにしてください100%とし)リストでグループ内のPKを追加することができます。もちろんPKがあると仮定します;)
別の方法。
SELECT U.*
FROM dbo.Users U
CROSS APPLY (SELECT Town INTERSECT SELECT 'Townsville' ) CA;
「ちょうど楽しみのために、」あなたは使うことができorder by
てtop(1) with ties
select top(1) with ties *
from dbo.Users
order by case when town = 'Townsville' then 1 else 2 end;
Townsville
ケースは1
ifを返すため、これはすべての行を最初に並べますtown = 'Townsville'
。他のすべての行には2
、ケースによって返されます。
このwith ties
句により、クエリは、返された行の最後の場所の「タイ」であるすべての行を返します。使用top(1)
との組み合わせではwith ties
、次にorder by句で使用される式の最初の行と同じ値を持つすべての行を返します。
Martin Smithがコメントで指摘したように、テーブルに存在しない町を要求すると、すべての行が返されることに注意してください。
データベースのXMLのことを恐れなければ、nodes()関数で述語を利用できます。
Paul Whiteからセットアップを借りています。
select T.X.value('(UserName/text())[1]', 'varchar(30)') as UserName,
T.X.value('(Town/text())[1]', 'varchar(30)') as Town
from (
select *
from @Example
for xml path('row'), type
) as C(X)
cross apply C.X.nodes('/row[Town = "Townsville"]') as T(X);
別のバージョンtop
とorder by
その実際の作業では、既存のない町を検索するとき。
select top(
select sum(case when town = 'Townsville' then 1 end)
from @Example
) *
from @Example
order by case when town = 'Townsville' then 1 else 2 end
ここには2つの異なるものがあります。
SELECT * FROM Users
WHERE town = 'Townsville'
返される行の数を、town =の行のみに制限しますTownsville
SELECT *, town('Townsville') FROM Users
Townsville
と呼ばれる関数にリテラルを渡しtown
ます。クエリによって返される行を制限しません。実際、関数が単一の値以外を返す場合、エラーが発生します。
クエリから返される行の数を制限する方法は他にもあります。たとえば、HAVING句。ただし、他にもいくつかの要件があります。
SELECT town FROM Users
GROUP BY town
HAVING town = 'Townsville'
または、インナージョイン。ただし、2番目のテーブルがない場合、これは少し奇妙です。
SELECT * FROM Users
INNER JOIN (SELECT 1 col1) UselessTable
ON Users.town = 'Townsville'
ここに、私がまだ見ない、それを行うばかげた完全に論理的な方法があります....
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- Our important work should be all the database cares about
GO
BEGIN TRANSACTION
DECLARE @MyTableVar table(<all columns in order from the user table>, oldtown VARCHAR(50));
UPDATE users
SET town = N'Townsville'
OUTPUT
inserted.* -- We don't want to have to type out the columns because that would be too much work
deleted.town
INTO @MyTableVar;
--Display the result set of the table variable to prevent undesirables from sullying our output by inserting incorrect data even though we should have exclusive access.
SELECT * -- Select everything we want except for the 'oldtown' column because that data was probably wrong anyway
FROM @MyTableVar;
UPDATE u -- We don't want to be bad stewards of our data
SET
town = oldtown
FROM users u
INNER JOIN @MyTableVar mtv ON mtv.town = u.town, <Match up all the columns to REALLY ensure we are matching the proper row>
COMMIT TRANSACTION -- Make sure we save our work
なぜこれが最初に提案されなかったのか想像できません。:)