Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在SQL Server中以字符串形式获取明细表记录_Sql_Sql Server_Sql Server 2005 - Fatal编程技术网

如何在SQL Server中以字符串形式获取明细表记录

如何在SQL Server中以字符串形式获取明细表记录,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我在数据库中有一个表,其中包含以下医院名称: +------------+--------------+ | HospitalID | HospitalName | +------------+--------------+ | 1 | Hosp1 | | 2 | Hosp2 | | 3 | Hosp3 | | 4 | Hosp4 | +------------+---

我在数据库中有一个表,其中包含以下医院名称:

+------------+--------------+
| HospitalID | HospitalName |
+------------+--------------+
|          1 | Hosp1        |
|          2 | Hosp2        |
|          3 | Hosp3        |
|          4 | Hosp4        |
+------------+--------------+
还存在另一个表,其中包含活动名称,如下所示:

+------------+--------------+
| ActivityID | ActivityName |
+------------+--------------+
|          1 | Act1         |
|          2 | Act2         |
|          3 | Act3         |
|          4 | Act4         |
|          5 | Act5         |
+------------+--------------+
+----+------------+------------+
| ID | HospitalID | ActivityID |
+----+------------+------------+
|  1 |          1 |          1 |
|  2 |          1 |          2 |
|  3 |          1 |          5 |
|  4 |          2 |          1 |
|  5 |          2 |          3 |
|  6 |          3 |          2 |
+----+------------+------------+
+--------------+------------------+
| HospitalName |  ActivityNames   |
+--------------+------------------+
| Hosp1        | Act1, Act2, Act5 |
| Hosp2        | Act1, Act3       |
| Hosp3        | Act2             |
| Hosp4        |                  |
+--------------+------------------+
这些表之间存在N*M关系,即每个医院可以执行不同的活动。因此,需要另一个表格,如下所示:

+------------+--------------+
| ActivityID | ActivityName |
+------------+--------------+
|          1 | Act1         |
|          2 | Act2         |
|          3 | Act3         |
|          4 | Act4         |
|          5 | Act5         |
+------------+--------------+
+----+------------+------------+
| ID | HospitalID | ActivityID |
+----+------------+------------+
|  1 |          1 |          1 |
|  2 |          1 |          2 |
|  3 |          1 |          5 |
|  4 |          2 |          1 |
|  5 |          2 |          3 |
|  6 |          3 |          2 |
+----+------------+------------+
+--------------+------------------+
| HospitalName |  ActivityNames   |
+--------------+------------------+
| Hosp1        | Act1, Act2, Act5 |
| Hosp2        | Act1, Act3       |
| Hosp3        | Act2             |
| Hosp4        |                  |
+--------------+------------------+
我想写一个select语句,在字符串字段中选择医院名称及其相关活动,如下所示:

+------------+--------------+
| ActivityID | ActivityName |
+------------+--------------+
|          1 | Act1         |
|          2 | Act2         |
|          3 | Act3         |
|          4 | Act4         |
|          5 | Act5         |
+------------+--------------+
+----+------------+------------+
| ID | HospitalID | ActivityID |
+----+------------+------------+
|  1 |          1 |          1 |
|  2 |          1 |          2 |
|  3 |          1 |          5 |
|  4 |          2 |          1 |
|  5 |          2 |          3 |
|  6 |          3 |          2 |
+----+------------+------------+
+--------------+------------------+
| HospitalName |  ActivityNames   |
+--------------+------------------+
| Hosp1        | Act1, Act2, Act5 |
| Hosp2        | Act1, Act3       |
| Hosp3        | Act2             |
| Hosp4        |                  |
+--------------+------------------+
我已经使用游标为ActivityNames字段编写了select语句,但它没有得到优化,并且随着记录数的增加,系统性能会下降


关于如何解决这个问题有什么解决方案或建议吗?

您可以使用json来提高前端的性能。 如果您使用的是开源数据库,则没有特定的解决方案

尝试使用IBMDB2或ORACLE数据库来确保应用程序的性能


然后生成json数据。您会发现速度有所提高

只需选择即可。不需要循环或光标。循环将使性能降低

using STUFF function to achieve your result :

CREATE TABLE #Hospital(HospitalID INT,HospitalName VARCHAR(100))
CREATE TABLE #Activity(ActivityID INT,ActivityName VARCHAR(100))
CREATE TABLE #RelationShip(Id INT,HospId INT,ActId INT)
CREATE TABLE #ConCat(HospitalID  INT ,HospName VARCHAR(100), ActName   
VARCHAR(100),UpFlag TINYINT DEFAULT(0))
DECLARE @HospId INT = 0,@String VARCHAR(200) = ''

INSERT INTO #Hospital(HospitalID ,HospitalName )
SELECT 1,'Hosp1' UNION ALL
SELECT 2,'Hosp2' UNION ALL
SELECT 3,'Hosp3' UNION ALL
SELECT 4,'Hosp4'    

INSERT INTO #Activity(ActivityID ,ActivityName )
SELECT  1,'Act1' UNION ALL 
SELECT  2,'Act2' UNION ALL 
SELECT  3,'Act3' UNION ALL 
SELECT  4,'Act4' UNION ALL 
SELECT  5,'Act5' 

INSERT INTO #RelationShip(ID,HospId,ActId)
SELECT  1 ,          1 ,          1 UNION ALL
SELECT    2 ,          1 ,          2 UNION ALL
SELECT    3 ,          1 ,          5 UNION ALL
SELECT    4 ,          2 ,          1 UNION ALL
SELECT    5 ,          2 ,          3 UNION ALL
SELECT    6 ,          3 ,          2 

SELECT HospitalName , STUFF(  ( SELECT  ',' + ActivityName FROM #Activity   
JOIN #RelationShip ON ActId = ActivityID WHERE HospId = HospitalID FOR XML   
PATH('') ),1,1,'')  
FROM #Hospital
GROUP BY HospitalID,HospitalName 

***FOR SQLServer2005 Use below code***

  INSERT INTO #ConCat (HospitalID ,HospName) 
  SELECT DISTINCT HospitalID ,HospitalName 
  FROM #Hospital

  WHILE EXISTS(SELECT 1 FROM #ConCat WHERE UpFlag = 0)
  BEGIN

     SELECT @HospId =  HospitalID FROM #ConCat WHERE UpFlag = 0 ORDER BY   
     HospitalID

     SET @String = ''
     SELECT @String = ISNULL(@String,'') + CAST(A.ActivityName AS VARCHAR) +    
     ',' FROM 
      (
        SELECT ActivityName 
        FROM #RelationShip 
        JOIN #Activity ON ActId = ActivityID
        WHERE HospId = @HospId
      ) A 

      UPDATE #ConCat SET UpFlag = 1,ActName = CASE WHEN @String = '' THEN    
       @String ELSE SUBSTRING(@String,0,LEN(@String) ) END WHERE HospitalID    
       = @HospId

     END

     SELECT * FROM #ConCat
因此,模式将是

CREATE TABLE #HOSPITAL( HOSPITALID INT, HOSPITALNAME VARCHAR(20))

INSERT INTO #HOSPITAL
SELECT 1, 'HOSP1' 
UNION ALL 
SELECT 2 , 'HOSP2' 
UNION ALL 
SELECT 3 ,'HOSP3' 
UNION ALL 
SELECT 4 , 'HOSP4' 



CREATE TABLE #ACTIVITY( ActivityID INT, ActivityName VARCHAR(50) )

INSERT INTO #ACTIVITY                          
SELECT          1,  'Act1'    
UNION ALL     
SELECT          2,  'Act2'  
UNION ALL        
SELECT          3,  'Act3' 
UNION ALL         
SELECT          4,  'Act4'
UNION ALL          
SELECT          5,  'Act5'         


CREATE TABLE #HOSPITAL_ACT_MAP(ID INT, HospitalID INT, ActivityID INT)

INSERT INTO #HOSPITAL_ACT_MAP
SELECT 1, 1, 1 
UNION ALL 
SELECT 2, 1, 2 
UNION ALL 
SELECT 3, 1, 5 
UNION ALL 
SELECT 4, 2, 1 
UNION ALL 
SELECT 5, 2, 3 
UNION ALL 
SELECT 6, 3, 2 
并使用CTE进行如下选择

;WITH CTE AS (
SELECT DISTINCT H.HOSPITALNAME, A.ActivityName FROM #HOSPITAL_ACT_MAP HA
INNER JOIN #HOSPITAL H ON HA.HospitalID = H.HOSPITALID
INNER JOIN #ACTIVITY A ON HA.ActivityID = A.ActivityID
)

SELECT  HOSPITALNAME
, (SELECT STUFF((SELECT ','+ActivityName FROM CTE C1 
WHERE  C1.HOSPITALNAME = C.HOSPITALNAME 
FOR XML PATH('')),1,1,'')) 
FROM CTE C
GROUP BY HOSPITALNAME
根据评论编辑

如果您不能使用
CTE
Stuff
请使用方法2

DECLARE @TAB TABLE (HOSPITALNAME VARCHAR(20),ActivityName VARCHAR(20) )

INSERT INTO @TAB
SELECT DISTINCT H.HOSPITALNAME, A.ActivityName FROM #HOSPITAL_ACT_MAP HA
INNER JOIN #HOSPITAL H ON HA.HospitalID = H.HOSPITALID
INNER JOIN #ACTIVITY A ON HA.ActivityID = A.ActivityID

SELECT HOSPITALNAME, SUBSTRING(ACTIVITIES,1, LEN(ACTIVITIES)-1) FROM(

SELECT DISTINCT HOSPITALNAME,(SELECT ActivityName+',' FROM @TAB T1 
WHERE  T1.HOSPITALNAME = T.HOSPITALNAME 
FOR XML PATH('') ) AS ACTIVITIES FROM @TAB T

)A

注意:出于性能目的,我将中间结果存储在@TAB(表变量)上。如果你愿意,你可以直接用Sub-Query查询。

Faruk他已经标记了Sqlserver,所以请根据它给出答案。我正在使用SQLServer2005作为数据库服务器。我的问题是如何获取ActivityNames字段。您介意提供更详细的信息吗?不确定sql server 2005是否支持
功能,非常确定它不支持cte。但我似乎记得它确实支持xml的
…使用CTE和其他东西编写的方法在SQLServer2005和2008中对我都很好。感谢您的宝贵意见。@shahram Akbarinasaji,您使用了内部联接。然后是如何获得“HOSP4”值的。它与活动和映射无关。@Shakermirza,您使用了内部联接。然后是如何获得“HOSP4”值的。它与活动和映射无关。@Mansoor,更改为将解决此问题。不确定sql server 2005是否支持
东西
,但我似乎记得它确实支持
for xml
。@ZoharPeled 2005支持stuff@t-克劳森:很高兴知道,以防我发明了时间机器:-),但在这篇微软的文档中,它是从2008年@t-clausen开始支持的。dk@ShakeerMirza你说得对。我使用的是第一个建议-升级数据库。Microsoft不再支持Sql server 2005。