看文章看到了个阿里SQL面试题

好奇都是要学的 2019-05-09 04:02:41
一个表一千个列值为true和false,写sql 查询 有300个列值为true的行
挺有意思的。

我的想法是是把case 列明 TURE when换成1 然后重第一列加到第1000列 数值>300就赢了
但是也要写1000个case 太不行了,
然后我想写个循环 1000次 拼装了他。

这2个的前提 都得是 列明一样后面多个值 比如 第一列a1 第二列a2 我可以循环, 如果列明完全不一样就不行了

我就想重系统表里取出这个表的 所有列, 然后在拼装。

各位大神有什么更好的想法吗

...全文
2296 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
天涯特困生 2019-05-18
  • 打赏
  • 举报
回复
--Temp table for test
CREATE TABLE #t1(b1 varchar(10), b2 varchar(10), b3 varchar(10),b4 varchar(10),b5 varchar(10));
INSERT INTO #t1 VALUES('false','false','true','true','false'),('false','false','true','false','false'),('false','false','false','false','false')
,('true','true','true','false','false'),('true','true','true','false','true'),('true','true','true','true','true');

--列的数目. demo中为5 (b1~b5). 如题的实例则设置为1000
DECLARE @iCol INT = 5

--需要为true的列数需大于此数, domo中为2。如题的实例则设置为300
DECLARE @iTrueCount INT = 2		

--CTE to concat all cols
;WITH CTE_T1 AS (
SELECT CAST(
		(
		   SELECT (
				  SELECT T2.N.value('./text()[1]',  'varchar(max)')
				  FROM (
					   SELECT T.*
					   for xml path(''), type
					   ) as T1(N)
					cross apply T1.N.nodes('/*') as T2(N)
				  for xml path(''), type
				  ).value('substring(./text()[1], 1)',  'varchar(max)')
		   for xml path(''), type
		 )
		 AS VARCHAR(8000)) AS Val,*
	FROM #t1 as T
)

--Len('true')=4, Len('False')=5, 若都为false, 则总长度为5*@iCol, 没多一个true,总长度减1,所以长度差值即为true列的数目
SELECT * 
FROM CTE_T1
WHERE LEN(Val) < 5*@iCol - @iTrueCount

--Cleaning
DROP TABLE #t1
  • 打赏
  • 举报
回复
引用 11 楼 疯狂的疯 的回复:
动态SQL所有列聚合为一列,为0 的都替换为空,求个len 大于300,不过也不是很简单。。坐等简单办法
你这个又替换 又取长度的。 不如相加 求值了。
xiaoxiangqing 2019-05-13
  • 打赏
  • 举报
回复
没有比较简单的办法
xzxmustwin 2019-05-13
  • 打赏
  • 举报
回复
UNPIVOT 数据量不大的时候 我看行。
ackermander 2019-05-12
  • 打赏
  • 举报
回复
引用 9 楼 ackermander 的回复:
为什么我觉得用top 300就好了
哦哦哦,看错了
ackermander 2019-05-12
  • 打赏
  • 举报
回复
为什么我觉得用top 300就好了
疯狂的疯 2019-05-12
  • 打赏
  • 举报
回复
动态SQL所有列聚合为一列,为0 的都替换为空,求个len 大于300,不过也不是很简单。。坐等简单办法
雨夹雪 2019-05-11
  • 打赏
  • 举报
回复

--这个不用动态
--等待更好的
CREATE TABLE #T
(
A BIT,
B BIT,
C BIT,
D BIT,
E BIT
)

INSERT INTO #T VALUES(1,0,1,0,1),(0,0,1,0,1),(1,0,1,0,0)

WITH ct
AS
(
SELECT *,ROW_NUMBER() OVER(ORDER BY GETDATE())+1 AS id FROM #T
)
SELECT * FROM
(
SELECT *, (SELECT * FROM ct WHERE id=A.id FOR XML PATH('')) AS cpath FROM ct A
) A WHERE LEN(cpath)-LEN(REPLACE(cpath,'>1<','><'))=2

  • 打赏
  • 举报
回复
unpivot 汇总后 匹配查询
  • 打赏
  • 举报
回复
引用 4 楼 雨夹雪 的回复:

--等待更好的
CREATE TABLE #T
(
	A BIT,
	B BIT,
	C BIT,
	D BIT,
	E BIT
)

INSERT INTO #T VALUES(1,0,1,0,1),(0,0,1,0,1),(1,0,1,0,0)


DECLARE @sql VARCHAR(max)=''
DECLARE @where VARCHAR(max)=''
SET @sql='SELECT  *  FROM #T  WHERE 2=(select sum(value)  from (select 0 As value  {where}) T )'
SET @where=(SELECT  ' union all select '+name  FROM tempdb.sys.columns WHERE OBJECT_ID=object_id('tempdb..#T')FOR XML PATH(''))
SET @sql=REPLACE(@sql,'{where}',@where)
EXEC (@sql)
 
我也是这么想的,
雨夹雪 2019-05-10
  • 打赏
  • 举报
回复

--等待更好的
CREATE TABLE #T
(
A BIT,
B BIT,
C BIT,
D BIT,
E BIT
)

INSERT INTO #T VALUES(1,0,1,0,1),(0,0,1,0,1),(1,0,1,0,0)


DECLARE @sql VARCHAR(max)=''
DECLARE @where VARCHAR(max)=''
SET @sql='SELECT * FROM #T WHERE 2=(select sum(value) from (select 0 As value {where}) T )'
SET @where=(SELECT ' union all select '+name FROM tempdb.sys.columns WHERE OBJECT_ID=object_id('tempdb..#T')FOR XML PATH(''))
SET @sql=REPLACE(@sql,'{where}',@where)
EXEC (@sql)

  • 打赏
  • 举报
回复
居然没有人,高手都去哪里了
  • 打赏
  • 举报
回复
还有一个补充 得看这个列的值 是 bool类型 还是 字符类型, 如果是bool类型 , 可以把case 省略
  • 打赏
  • 举报
回复
网上找的答案,我非常不认可。

select * from your_table as yt inner join ( select id as id, col1+col2+...+col1000 as s from your_table ) as t on [yt.id] = [t.id] and t.s = 300

34,590

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧