ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 2116|回复: 6

[原创] 有意思的SQL题目

[复制链接]

TA的精华主题

TA的得分主题

发表于 2012-11-17 11:44 | 显示全部楼层 |阅读模式
本帖最后由 wuxiang_123 于 2012-11-17 11:48 编辑

今天在回答一个会员的问题,问题如下:
需要将下图A列数值区分正负值,并列出返回如C:D列效果。
问题.jpg

使用VBA、和函数相信对于各位VBA和函数高手都很简单(偶这两方面都是菜鸟,不会),如果结果不需要返回重复值,那么,使用SQL也很简单,可以使用我的转置贴语句实现:

  1. TRANSFORM MIN(数值)
  2. SELECT NULL FROM
  3. (SELECT A.正负,A.数值,SUM(1) AS 排名 FROM
  4. (SELECT DISTINCT SWITCH(数值>0,"正数",数值<0,"负数") AS 正负,数值 FROM [SHEET1$] WHERE 数值)A,
  5. (SELECT DISTINCT SWITCH(数值>0,"正数",数值<0,"负数") AS 正负,数值 FROM [SHEET1$] WHERE 数值)B
  6. WHERE A.正负=B.正负 AND A.数值>=B.数值
  7. GROUP BY A.正负,A.数值)
  8. GROUP BY 排名
  9. PIVOT 正负
复制代码
去重复值.jpg

但结果要求返回重复值,而SQL却没有行的概念,无法区分相同项,此时,我们需要使用辅助列来完成:

辅助.jpg

辅助的作用在于为我们区分相同的项,也可以为我们获取每个记录在数据源中的位置,此时,我们就可以利用辅助列使用以下语句:

  1. TRANSFORM MIN(数值)
  2. SELECT NULL FROM
  3. (SELECT A.正负,A.数值,A.辅助,SUM(1) AS 位置 FROM
  4. (SELECT 辅助,SWITCH(数值>0,"正数",数值<0,"负数") AS 正负,数值 FROM [SHEET1$] WHERE 数值)A,(SELECT 辅助,SWITCH(数值>0,"正数",数值<0,"负数") AS 正负,数值 FROM [SHEET1$] WHERE 数值)B
  5. WHERE A.正负=B.正负 AND A.辅助<=B.辅助
  6. GROUP BY A.正负,A.数值,A.辅助)
  7. GROUP BY 位置
  8. PIVOT 正负
复制代码
使用辅助.jpg

也许你会疑问:那新增数据不就是需要重新在辅助列输入公式?此时,我们完全可以借用列表功能完成公式的自动填充,然后我们隐藏数据源中的辅助列就可以了。
插入表格.png

那有没有不在数据源插入辅助列的方法呢?这时候我们需要使用到【连接属性】-【属性】中的【包含行号】。
属性.png
此时将出现一个“_RowNum” 新字段,作用等价于我们上文使用的辅助列,在返回的结果表中插入了一个行号,然后我们再以返回结果作为数据源进行交叉表查询。
  1. TRANSFORM MIN(数值)
  2. SELECT NULL FROM
  3. (SELECT A.正负,A.数值,A.[_RowNum],SUM(1) AS 位置 FROM
  4. (SELECT [_RowNum],SWITCH(数值>0,"正数",数值<0,"负数") AS 正负,数值 FROM [SHEET4$] WHERE 数值)A,(SELECT [_RowNum],SWITCH(数值>0,"正数",数值<0,"负数") AS 正负,数值 FROM [SHEET4$] WHERE 数值)B
  5. WHERE A.正负=B.正负 AND A.[_RowNum]<=B.[_RowNum]
  6. GROUP BY A.正负,A.数值,A.[_RowNum])
  7. GROUP BY 位置
  8. PIVOT 正负
复制代码
使用此方法,纯属取巧,不能适应数据源的动态更新,不可取。




该贴已经同步到 wuxiang_123的微博

提取正负数.rar

13.83 KB, 下载次数: 56

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2012-11-17 12:06 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
吴版,你研究太深入了

TA的精华主题

TA的得分主题

发表于 2012-11-17 13:09 | 显示全部楼层
这里文章太大了。SQL那几句基本语句我也学了用了一段时间了,但如此游刃有余,尚是学习目标啊。

TA的精华主题

TA的得分主题

发表于 2012-11-17 13:12 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
moon_2000 发表于 2012-11-17 13:09
这里文章太大了。SQL那几句基本语句我也学了用了一段时间了,但如此游刃有余,尚是学习目标啊。

是很庞大的。

TA的精华主题

TA的得分主题

发表于 2012-11-17 14:27 | 显示全部楼层
香帅厉害~  鼓捣了半天还是绕到转置这里了,级别太高,不懂~

TA的精华主题

TA的得分主题

发表于 2012-11-17 20:34 | 显示全部楼层
这个问题在Server SQL中比较好解决
[code=sql]--方法一
DECLARE @TB1 TABLE(ID INT IDENTITY,NUM INT)
DECLARE @TB2 TABLE(ID INT IDENTITY,NUM INT)
INSERT INTO @TB1
SELECT NUM FROM TEST WHERE num > 0;
INSERT INTO @TB2
SELECT NUM FROM TEST WHERE num < 0;
SELECT A.NUM,B.NUM
FROM @TB1 AS A
LEFT JOIN @TB2 AS B
ON A.ID = B.ID;

--方法二
;WITH A AS
(SELECT ROW_NUMBER()OVER(ORDER BY GETDATE()) AS ID,NUM
FROM TEST WHERE num > 0),
B AS
(SELECT ROW_NUMBER()OVER(ORDER BY GETDATE()) AS ID,NUM
FROM TEST WHERE num < 0)
SELECT A.NUM,B.NUM
FROM A
LEFT JOIN B
ON A.ID = B.ID;[/code]
1.gif

点评

是的,而且,印象中ROW_NUMBER是2005版本以上才有。  发表于 2012-11-18 09:40

TA的精华主题

TA的得分主题

发表于 2012-11-18 15:29 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-28 20:06 , Processed in 0.046287 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表