テーブルがあります_[CourseMaster]
_ LIKE
_CourseId CourseName
-----------------------
01 ABC
02 DEF
03 GHI
04 JKL
05 MNO
06 PQR
07 STU
_
そして、私は別のテーブル_[StudentMaster]
_を学生の詳細LIKEに持っています
_ROLLNO NAME ADDRESS Course
------------------------------------------------
12345 RAM RAM ADDRESS 01,02,06
25695 HARI HARI ADDRESS 02,06
89685 JEFF JEFF ADDRESS 03,05,06,07
47896 DAISY DAISY ADDRESS 03
_
ここでは、CourseName
(Not CourseId
)を使用して生徒の詳細を取得します。
Course
の値がコンマで区切られていない場合、結合で詳細をフェッチするのは非常に単純なquery
になります。
私の知る限りでは、2つのqueries
を実行して同じ結果を得ることができます。学生の詳細を_[StudentMaster]
_からフロントエンドにフェッチするための1つのクエリ。そして、ループを通じてCourseName
を対応させることにより、_[CourseMaster]
_からCourseId
のみをフェッチするための他の1つ。
しかし、この小さなタスクで2つのquery
を書くのではなく、1つのqueries
だけで結果を取得したいという事実。
100%可能だと思います。そして、私の期待される結果は次のようになります:
_ROLLNO NAME ADDRESS Course
-------------------------------------------
12345 RAM RAM ADDRESS ABC,DEF,PQR
25695 HARI HARI ADDRESS DEF,PQR
89685 JEFF JEFF ADDRESS GHI,MNO,PQR,STU
47896 DAISY DAISY ADDRESS GHI
_
ありがとうございました。貴重なご提案をいただければ幸いです。
カンマで区切られた値を1つのタプルに詰め込むのではなく、学生が受講するコースのジャンクションテーブルが必要です。この次善の設計のためにこれがあなたが持つ最後の問題だと思うなら、あなたは大きな驚きに直面しています。あなたは本当にこのプロジェクトの所有者に正規化について読んでもらう必要があります-はい、スキーマを変更するのは苦痛ですが、それをそのままにしておくことの制限に常に対処しています。
とにかく、それが言われて、あなたは分割関数を必要とします。コンマで区切られた値は数値であるため、XML関数のバリエーションを使用して回避できます。他にもいくつかあります このブログの投稿では 。
CREATE FUNCTION dbo.SplitStrings_XML
(
@List VARCHAR(MAX),
@Delimiter CHAR(1) = ','
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'varchar(8000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
今、あなたのクエリは:
;WITH x AS
(
SELECT s.ROLLNO, s.Name, s.Address, c.CourseId, c.CourseName
FROM dbo.StudentMaster AS s
CROSS APPLY dbo.SplitStrings_XML(s.Course, default) AS f
INNER JOIN dbo.CourseMaster AS c
ON f.item = c.CourseId
)
SELECT ROLLNO, Name, Address, STUFF((
SELECT ',' + CourseName FROM x AS x2
WHERE x2.ROLLNO = x.ROLLNO
ORDER BY CourseId FOR XML PATH,
TYPE).value(N'.[1]',N'varchar(max)'), 1, 1, '')
FROM x
GROUP BY ROLLNO, Name, Address;
繰り返しますが、これは複雑なソリューションであり、データベース構造が劣っているため、次に実行する必要のあるクエリも同様に複雑で面倒です。このタイプのデザインがトピックについてのほぼすべてのブログ、エッセイ、または本で反対されている理由があります...
Aaron Bertrandがコンマ区切りの値を作成するときに提供するものと同じソリューションですが、CourseMaster.CourseId
とStudentMaster.Course
の値を接続する方法が少し異なります。
MS SQL Server 2014スキーマセットアップ:
create table dbo.CourseMaster
(
CourseId char(2),
CourseName char(3)
);
create table dbo.StudentMaster
(
ROLLNO char(5),
NAME varchar(10),
ADDRESS varchar(20),
Course varchar(100)
);
insert into dbo.CourseMaster values
('01', 'ABC'),
('02', 'DEF'),
('03', 'GHI'),
('04', 'JKL'),
('05', 'MNO'),
('06', 'PQR'),
('07', 'STU');
insert into dbo.StudentMaster values
('12345', 'RAM', 'RAM ADDRESS', '01,02,06'),
('25695', 'HARI', 'HARI ADDRESS', '02,06'),
('89685', 'JEFF', 'JEFF ADDRESS', '03,05,06,07'),
('47896', 'DAISY', 'DAISY ADDRESS', '03');
クエリ1:
select SM.ROLLNO,
SM.NAME,
SM.ADDRESS,
(
select ','+CM.CourseName
from dbo.CourseMaster as CM
where ','+SM.Course+',' like '%,'+CM.CourseId+',%'
for xml path(''), type
).value('substring(text()[1], 2)', 'varchar(max)') as Course
from dbo.StudentMaster as SM;
結果:
| ROLLNO | NAME | ADDRESS | Course |
|--------|-------|---------------|-----------------|
| 12345 | RAM | RAM ADDRESS | ABC,DEF,PQR |
| 25695 | HARI | HARI ADDRESS | DEF,PQR |
| 89685 | JEFF | JEFF ADDRESS | GHI,MNO,PQR,STU |
| 47896 | DAISY | DAISY ADDRESS | GHI |
StudentMaster
テーブルからリスト値を取得する簡単な方法(および結果に結合することができます)は、(前述のように分割文字列を使用して、関数が呼び出された列を返すと仮定して)各リスト項目の項目):
SELECT ROLLNO, NAME, ADDRESS, item
FROM StudentMaster
CROSS APPLY fSplitString(Course);
select D.DATE,D.DESCP,
(
select ','+S.NAME
from tb_schems as S
where ',' + D.SCHME + ',' like '%,' + cast(S.id as nvarchar(20)) + ',%'
for xml path(''), type
).value('substring(text()[1], 2)', 'varchar(max)') as SCHEME
from TB_DETAIL as D;