张同学的 SQL中对材料报价单的数据权限进行操作 (如列转行 行转列的处理) 学习一下.

SQL中对材料报价单的数据权限进行操作 (如列转行 行转列的处理)
--可以直接放到查询分析器执行
--判断测试表TmpTCIQuote是否有存在 不存在则创建
if NOT exists (select * from dbo.sysobjects where id = object_id(N'dbo.TmpTCIQuote') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN 
create table TmpTCIQuote(
CIQuotesID   int not null,             --材料报价单ID
cSubInvCode VARCHAR(100) NOT NULL,     --材料编码
cVen1       VARCHAR(50),    --材料厂编码1
cMVenName1  VARCHAR(200),    --材料厂名称1
cVen2       VARCHAR(50),    --材料厂编码2
cMVenName2  VARCHAR(200),    --材料厂名称2
cVen3       VARCHAR(50),    --材料厂编码3
cMVenName3  VARCHAR(200)    --材料厂名称3
primary key (CIQuotesID)
);
END 

--清空数据
TRUNCATE TABLE TmpTCIQuote

--插入默认数据
INSERT INTO TmpTCIQuote(CIQuotesID,cSubInvCode,cVen1,cMVenName1,cVen2,cMVenName2,cVen3,cMVenName3)
SELECT 1,'39010000098','100595','东莞利丰商标制造有限公司','100823','广州南沙经济技术开发区彩佳印花有限公司','100436','晋江市绿雨彩色印刷有限公司' UNION ALL 
SELECT 2,'39080000001','100823','广州南沙经济技术开发区彩佳印花有限公司','100595','东莞利丰商标制造有限公司',NULL,NULL UNION ALL 
SELECT 3,'39150000101','100436','晋江市绿雨彩色印刷有限公司',NULL,NULL,'100595','东莞利丰商标制造有限公司' UNION ALL 
SELECT 4,'39150000101','100436','晋江市绿雨彩色印刷有限公司',NULL,NULL,NULL,NULL

SELECT * FROM TmpTCIQuote

/*
原始数据
ID    材料编码  材料厂编码1     材料厂名称1   材料厂编码2     材料厂名称2    材料厂编码3     材料厂名称3
1 39010000098   100595 东莞利丰商标制造有限公司 100823 广州南沙经济技术开发区彩佳印花有限公司 100436 晋江市绿雨彩色印刷有限公司
2 39080000001   100823 广州南沙经济技术开发区彩佳印花有限公司 100595 东莞利丰商标制造有限公司 NULL NULL
3 39150000101   100436 晋江市绿雨彩色印刷有限公司 NULL NULL 100595 东莞利丰商标制造有限公司
4 39150000101   100436 晋江市绿雨彩色印刷有限公司 NULL NULL NULL NULL

描述:只显示对应的材料厂编码 不相关的材料厂编码用Y表示(表示对应的已经有其它材料供应商) 为空的材料厂编码用Null表示

假设只拥有材料厂编码100595的查看数据权限 其它材料厂编码不能查看 有其它材料厂编码用Y表示 空的用Null表示
最终结果如下:
ID    材料编码  材料厂编码1     材料厂名称1   材料厂编码2     材料厂名称2    材料厂编码3     材料厂名称3
1 39010000098   100595 东莞利丰商标制造有限公司   Y Y
2 39080000001    Y 100595 东莞利丰商标制造有限公司 Null
3 39150000101    Y   Null 100595 东莞利丰商标制造有限公司

*/
DECLARE @cVenValue VARCHAR(50)   --定义材料厂编码 
SET @cVenValue = '100595';       --只允许查看100595的材料厂编码
WITH T1 AS   --对三个材料厂编码进行列转行
(SELECT CIQuotesID,cSubInvCode,cVenValue,VenIndex = REPLACE(cVen,'cVen','') FROM TmpTCIQuote
UNPIVOT (cVenValue FOR cVen IN (cVen1,cVen2,cVen3)) cVen),
T2 AS  --显示包括的材料厂编码的信息
(SELECT CIQuotesID,cSubInvCode,cVenValue,VenIndex FROM T1 WHERE cVenValue = @cVenValue),
T3 AS  --显示其它材料厂编码的信息 材料厂编码用Y表示
(SELECT CIQuotesID,cSubInvCode,cVenValue = 'Y',VenIndex FROM T1 WHERE cVenValue <> @cVenValue AND ISNULL(cVenValue,'') <> ''),
T4 AS  --显示空材料厂编码的信息 材料厂编码用N表示
(SELECT CIQuotesID,cSubInvCode,cVenValue = 'N',VenIndex FROM T1 WHERE ISNULL(cVenValue,'') = ''),
T5 AS  --根据主键ID进行关联 
(SELECT t2.CIQuotesID, --材料报价单ID
        t2.cSubInvCode, --材料编码
        t2.cVenValue, --材料厂编码(显示相关的材料厂编码)
        t2.VenIndex, --材料厂编码对应的位置(显示相关的材料厂编码 如三个材料供应商 对应的1,2,3的位置)
        cVenValue2 = t3.cVenValue, --材料厂编码(显示不相关的材料厂编码)
        VenIndex2 = t3.VenIndex, --材料厂编码对应的位置(显示不相关的材料厂编码 如三个材料供应商 对应的1,2,3的位置)
        cVenValue3 = t4.cVenValue, --材料厂编码(显示空的材料厂编码)
        VenIndex3 = t4.VenIndex --材料厂编码对应的位置(显示空的材料厂编码 如三个材料供应商 对应的1,2,3的位置)
 FROM T2 
LEFT JOIN T3 ON t2.CIQuotesID = t3.CIQuotesID   --一定要Left Join 以显示包括的材料厂编码的信息的表为主
LEFT JOIN T4 ON t2.CIQuotesID = t4.CIQuotesID), --一定要Left Join 以显示包括的材料厂编码的信息的表为主
T6 AS --对包括的材料厂编码、其它的材料厂编码和空材料厂编码进行行转列的操作
(SELECT CIQuotesID, --材料报价单ID
       cSubInvCode, --材料编码
       cVenA1 = MAX(CASE WHEN VenIndex = 1 THEN cVenValue END), --材料厂编码1(显示相关的材料厂编码)
       cVenB1 = MAX(CASE WHEN VenIndex2 = 1 THEN cVenValue2 END), --材料厂编码1(显示不相关的材料厂编码)
       cVenC1 = MAX(CASE WHEN VenIndex3 = 1 THEN cVenValue3 END), --材料厂编码1(显示空的材料厂编码)
       cVenA2 = MAX(CASE WHEN VenIndex = 2 THEN cVenValue END), --材料厂编码2(显示相关的材料厂编码)
       cVenB2 = MAX(CASE WHEN VenIndex2 = 2 THEN cVenValue2 END), --材料厂编码2(显示不相关的材料厂编码)
       cVenC2 = MAX(CASE WHEN VenIndex3 = 2 THEN cVenValue3 END), --材料厂编码2(显示空的材料厂编码)
       cVenA3 = MAX(CASE WHEN VenIndex = 3 THEN cVenValue END), --材料厂编码3(显示相关的材料厂编码)
       cVenB3 = MAX(CASE WHEN VenIndex2 = 3 THEN cVenValue2 END), --材料厂编码3(显示不相关的材料厂编码)
       cVenC3 = MAX(CASE WHEN VenIndex3 = 3 THEN cVenValue3 END) --材料厂编码3(显示空的材料厂编码)
FROM T5 
GROUP BY CIQuotesID,cSubInvCode),
T7 AS 
(SELECT CIQuotesID, --材料报价单ID
cSubInvCode, --材料编码
       cVen1 = CASE     --材料厂编码(对应的材料厂编码、其它的材料厂编码和空材料厂编码 一定会有一个有存在 另外两个相关的都为空) 
WHEN LEN(ISNULL(cVenA1,'')) > LEN(ISNULL(cVenB1,'')) AND LEN(ISNULL(cVenA1,'')) > LEN(ISNULL(cVenC1,'')) THEN cVenA1
WHEN LEN(ISNULL(cVenB1,'')) > LEN(ISNULL(cVenA1,'')) AND LEN(ISNULL(cVenB1,'')) > LEN(ISNULL(cVenC1,'')) THEN cVenB1
WHEN LEN(ISNULL(cVenC1,'')) > LEN(ISNULL(cVenA1,'')) AND LEN(ISNULL(cVenC1,'')) > LEN(ISNULL(cVenB1,'')) THEN cVenC1
END,
       cVen2 = CASE --下面的Case判断就只取有值的赋给它对应的材料厂编码1,2,3本身
WHEN LEN(ISNULL(cVenA2,'')) > LEN(ISNULL(cVenB2,'')) AND LEN(ISNULL(cVenA2,'')) > LEN(ISNULL(cVenC2,'')) THEN cVenA2
WHEN LEN(ISNULL(cVenB2,'')) > LEN(ISNULL(cVenA2,'')) AND LEN(ISNULL(cVenB2,'')) > LEN(ISNULL(cVenC2,'')) THEN cVenB2
WHEN LEN(ISNULL(cVenC2,'')) > LEN(ISNULL(cVenA2,'')) AND LEN(ISNULL(cVenC2,'')) > LEN(ISNULL(cVenB2,'')) THEN cVenC2
END,
       cVen3 = CASE 
WHEN LEN(ISNULL(cVenA3,'')) > LEN(ISNULL(cVenB3,'')) AND LEN(ISNULL(cVenA3,'')) > LEN(ISNULL(cVenC3,'')) THEN cVenA3
WHEN LEN(ISNULL(cVenB3,'')) > LEN(ISNULL(cVenA3,'')) AND LEN(ISNULL(cVenB3,'')) > LEN(ISNULL(cVenC3,'')) THEN cVenB3
WHEN LEN(ISNULL(cVenC3,'')) > LEN(ISNULL(cVenA3,'')) AND LEN(ISNULL(cVenC3,'')) > LEN(ISNULL(cVenB3,'')) THEN cVenC3
END
FROM T6)  
SELECT * FROM T7

/*
最终结果如下:
ID    材料编码  材料厂编码1    材料厂编码2  材料厂编码3
1 39010000098 100595 Y Y
2 39080000001 Y 100595 NULL
3 39150000101 Y NULL 100595
*/
原文地址:https://www.cnblogs.com/wuyifu/p/2736865.html