与XML PATH连接

时间:2011-07-31 08:49:03

标签: sql sql-server

我有以下SP:

CREATE PROCEDURE AdvancedSearch
    @MechanicID nvarchar(50),
    @done bit,
    @sDate datetime,
    @eDate datetime
 AS
 SELECT   VehicleData.*, Vehicle.*, C5.dbo.debkart.navn,
          C5.dbo.DEBKART.ADRESSE1, C5.dbo.debkart.adresse2,
          Mechanic.MechanicName
 FROM     (((Vehicle INNER JOIN VehicleData ON Vehicle.ID = VehicleData.IDRegistrationNumber)
          INNER JOIN C5.dbo.debkart ON Vehicle.KeyC5 = c5.dbo.debkart.LXbenummer
          INNER JOIN Mechanic_VehicleData ON VehicleData.ID = Mechanic_VehicleData.PK_VehicleData))
          INNER JOIN Mechanic ON Mechanic_VehicleData.PK_Mechanic = Mechanic.ID
 WHERE    (@MechanicID IS NULL OR Mechanic.ID = @MechanicID) AND
          (@done IS NULL OR VehicleData.Done = @done) AND
          ((@sDate IS NULL OR @eDate IS NULL) OR VehicleData.DATE BETWEEN @sDate AND    @eDate)
 GO

我想在所有行中使用相同的VehicleData.ID连接MechanicName列,因此我们希望完全按照本文中的说明进行操作:Concatenate with XML Path 但只有一个领域是MechanicName。

我的问题是我无法弄清楚如何从我的SP内的帖子插入sql代码。

有人能帮助我吗?

更新:我有一些工作,我做了这个,它似乎返回我需要的东西,但有一个我进一步描述的问题:

SELECT  VehicleData.*, Vehicle.*, C5.dbo.debkart.navn, C5.dbo.DEBKART.ADRESSE1, C5.dbo.debkart.adresse2,
    STUFF(
    (SELECT
    ',' + MechanicName
    FROM Mechanic m
    INNER JOIN Mechanic_VehicleData vm ON m.ID = vm.PK_Mechanic
    WHERE vm.PK_VehicleData = VehicleData.ID 
    FOR XML PATH('')), 1, 1, ''
    ) AS 'Mechanics'
FROM (((Vehicle INNER JOIN VehicleData ON Vehicle.ID = VehicleData.IDRegistrationNumber)           
INNER JOIN C5.dbo.debkart ON Vehicle.KeyC5 = c5.dbo.debkart.LXbenummer))
ORDER BY VehicleData.ID

所以我到了需要添加WHERE子句的部分,现在我不知道在哪里放这些。我有办法搜索特定的MechanicID,完成标记和一些日期。我现在应该把它们放在哪里?

更新2

@谢谢marc帮助我,但我仍然有一个“小”问题:)

这是最终的SP:

CREATE PROCEDURE AdvancedSearch 
@MechanicID nvarchar(50),
@done bit,
@sDate datetime,
@eDate datetime
AS 
SELECT  VehicleData.*, Vehicle.*, C5.dbo.debkart.navn, C5.dbo.DEBKART.ADRESSE1, C5.dbo.debkart.adresse2,
    STUFF(
    (SELECT
    ',' + MechanicName
    FROM Mechanic m
    INNER JOIN Mechanic_VehicleData vm ON m.ID = vm.PK_Mechanic
    WHERE vm.PK_VehicleData = VehicleData.ID 
    FOR XML PATH('')), 1, 1, ''
    ) AS 'Mechanics'
FROM (Vehicle
INNER JOIN VehicleData ON Vehicle.ID = VehicleData.IDRegistrationNumber         
INNER JOIN C5.dbo.debkart ON Vehicle.KeyC5 = c5.dbo.debkart.LXbenummer), Mechanic, Mechanic_VehicleData
WHERE VehicleData.ID = Mechanic_VehicleData.PK_VehicleData 
AND Mechanic.ID = Mechanic_VehicleData.PK_Mechanic 
AND (@MechanicID IS NULL OR Mechanic.ID = @MechanicID) 
AND (@done IS NULL OR VehicleData.Done = @done)
AND ((@sDate IS NULL OR @eDate IS NULL) OR VehicleData.Date BETWEEN @sDate AND @eDate)
GO

如上所述它工作正常。我遇到的问题是,如果我运行EXECUTE AdvancedSearch null, null, null, null,查询完成需要4秒钟。如果我从SP运行查询它没有时间。我觉得很奇怪。为什么SP需要更长的时间?

1 个答案:

答案 0 :(得分:5)

首先尝试简化您的示例,然后在简化示例中找出如何执行此步骤 - 然后您可以将其重新集成到整个查询中。

试试这个 - 它适用于我的设置:

DECLARE @vehicle TABLE (VehID INT, VehName VARCHAR(50))
DECLARE @mechanic TABLE (MechanicID INT, MechanicName VARCHAR(50))
DECLARE @VehicleMechanic TABLE (VehID INT, MechanicID INT)

INSERT INTO @vehicle(VehID, VehName) VALUES(1, 'BMW 330i'),(2, 'Mini Cooper')

INSERT INTO @mechanic(MechanicID, MechanicName)
VALUES  (1, 'Joe'), (2, 'Jeff'), (3, 'Bob'), (4, 'Steve')

INSERT INTO @VehicleMechanic( VehID, MechanicID )
VALUES  ( 1, 1), (1, 2), (2, 1), (2, 3), (2, 4)

SELECT
    v.VehID, VehName, 
    STUFF(
    (SELECT
       ',' + MechanicName
     FROM @mechanic m 
     INNER JOIN @VehicleMechanic vm ON m.MechanicID = vm.MechanicID
     WHERE vm.VehID = v.VehID
     FOR XML PATH('')), 1, 1, ''
    ) AS 'Mechanics'
FROM @vehicle v

给我一​​个输出:

VehID  VehName      Mechanics
  1    BMW 330i     Joe,Jeff
  2    Mini Cooper  Joe,Bob,Steve

更新:很难验证任何内容,没有手头有你的数据库 - 但试试这个:

SELECT  
    vd.*, v.*, d.navn, d.ADRESSE1, D.adresse2,
    STUFF(
      (SELECT
         ',' + MechanicName
       FROM dbo.Mechanic m
       INNER JOIN dbo.Mechanic_VehicleData vm ON m.ID = vm.PK_Mechanic
       WHERE vm.PK_VehicleData = v.ID 
       FOR XML PATH('')), 1, 1, ''
      ) AS 'Mechanics'
FROM dbo.Vehicle v 
INNER JOIN dbo.VehicleData vd ON v.ID = vd.IDRegistrationNumber
-- if you need the mechnic, add this JOIN    
INNER JOIN dbo.Vehicle_Mechanic vm ON vm.VehicleID = v.VehicleID  
INNER JOIN C5.dbo.debkart d ON v.KeyC5 = d.LXbenummer

WHERE                   -- add your WHERE clause here
   vd.DoneFlag = 1    
   AND vd.SomeDate = GETDATE()
   AND vm.MechanicID = 4711          -- check for your specific mechanic
ORDER BY 
   vd.ID

如果它不起作用 - 你能否告诉我们你是否得到错误(以及它是什么),或者你是否得到错误的输出 - 它有什么问题?

任何WHERE子句都应添加到外部SELECT语句中 - 内部内容仅用于设置VehicleDataMechanic_VehicleDataMechanic表之间的关系。