有没有办法只在SELECT
列中包含某些数据的行而不使用WHERE
?
例如,如果我有这个:
SELECT * FROM Users
WHERE town = 'Townsville'
Run Code Online (Sandbox Code Playgroud)
有没有办法将WHERE
子句实现到SELECT
语句中?
就像是
SELECT *, town('Townsville') FROM Users
Run Code Online (Sandbox Code Playgroud)
这是一个奇怪的问题,但这是我的同龄人问过的问题
Mar*_*son 17
不确定这是否是您正在寻找的那种疯狂的东西......
免责声明:我完全不知道您为什么要使用它。
SELECT *
FROM Users AS u
INNER JOIN (SELECT 'Townsville' town) towns
ON towns.town = u.Town;
Run Code Online (Sandbox Code Playgroud)
Pau*_*ite 17
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');
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
-- :)
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;
Run Code Online (Sandbox Code Playgroud)
输出:
?????????????????????????
? UserName ? Town ?
?????????????????????????
? Charles ? Townsville ?
? Dan ? Townsville ?
?????????????????????????
Run Code Online (Sandbox Code Playgroud)
最后一个例子:
?????????????????????????
? UserName ? Town ?
?????????????????????????
? Charles ? Townsville ?
? Charles ? Townsville ?
? Charles ? Townsville ?
? Charles ? Townsville ?
? Dan ? Townsville ?
?????????????????????????
Run Code Online (Sandbox Code Playgroud)
在这里试试: Stack Exchange Data Explorer
Mar*_*ith 15
其它的办法。
SELECT U.*
FROM dbo.Users U
CROSS APPLY (SELECT Town INTERSECT SELECT 'Townsville' ) CA;
Run Code Online (Sandbox Code Playgroud)
Mik*_*son 14
“只是为了好玩”,您可以使用order by
withtop(1) with ties
select top(1) with ties *
from dbo.Users
order by case when town = 'Townsville' then 1 else 2 end;
Run Code Online (Sandbox Code Playgroud)
这将对所有行进行排序,Townsville
因为 case 返回1
if town = 'Townsville'
。所有其他行将有一个2
由案例返回。
该with ties
子句使查询返回与返回的行中最后一个位置“并列”的所有行。使用top(1)
结合with ties
然后将返回具有相同的值作为表达式中的第一行由子句中的顺序使用的所有行。
请注意,正如 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);
Run Code Online (Sandbox Code Playgroud)
与另一个版本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
Run Code Online (Sandbox Code Playgroud)
你在这里有两种不同的东西。
SELECT * FROM Users
WHERE town = 'Townsville'
Run Code Online (Sandbox Code Playgroud)
将您返回的行数限制为仅城镇 =Townsville
SELECT *, town('Townsville') FROM Users
Run Code Online (Sandbox Code Playgroud)
将把文字传递Townsville
给一个名为town
. 它不会限制查询返回的行,事实上,如果函数返回的不是单个值,你将得到一个错误。
还有其他方法可以限制您从查询中返回的行数。例如 HAVING 子句。但它还有其他几个要求。
SELECT town FROM Users
GROUP BY town
HAVING town = 'Townsville'
Run Code Online (Sandbox Code Playgroud)
或者一个 INNER JOIN 虽然如果你没有第二个表,这个有点奇怪。
SELECT * FROM Users
INNER JOIN (SELECT 1 col1) UselessTable
ON Users.town = 'Townsville'
Run Code Online (Sandbox Code Playgroud)
这是一个使用公用表表达式 (CTE) 的示例。
with Town as
(
select 'Townsville' as Town
)
select *
from Users u
join Town t on u.Town = t.Town
Run Code Online (Sandbox Code Playgroud)
那么你可以这样做:
SELECT A.*
FROM Users A
INNER JOIN Users B ON A.Id = B.Id AND B.town = 'Townsville'
Run Code Online (Sandbox Code Playgroud)
严格来说,您没有使用 WHERE 子句
这是一种愚蠢的完全合乎逻辑的方法,我还没有看到......
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
Run Code Online (Sandbox Code Playgroud)
我无法想象为什么这不是建议的第一件事。:)