SQL将多列放入一列

时间:2011-12-08 15:58:53

标签: sql-server sql-server-2008 tsql reporting-services ssrs-2008

我有这个用于创建报告的查询:

SELECT DISTINCT 
    Appointment.ActivityId, Appointment.ScheduledStart, Appointment.OwnerIdName, Contact.AccountIdName, Appointment.new_ContactPersonName, 
        Appointment.Subject, Appointment.new_ColderNotes, Account.AccountId, Contact_1.ContactId, SystemUser.SystemUserId, SystemUser.FullName AS OptionalOwner, 
        Contact_1.FullName AS OptionalContact, Account.Name AS OptionalAccount, ActivityParty.PartyId, ActivityParty.ParticipationTypeMask, 
        Contact_1.FullName AS RequiredContact, Account.Name AS RequiredAccount, SystemUser.FullName AS RequiredOwner, Account.new_BusinessUnit
FROM
    Contact AS Contact_1 RIGHT OUTER JOIN
        Account RIGHT OUTER JOIN
        SystemUser RIGHT OUTER JOIN
        Appointment INNER JOIN
        ActivityParty ON Appointment.ActivityId = ActivityParty.ActivityId ON SystemUser.SystemUserId = ActivityParty.PartyId ON Account.AccountId = ActivityParty.PartyId ON
        Contact_1.ContactId = ActivityParty.PartyId LEFT OUTER JOIN
        Contact ON Appointment.new_ContactPerson = Contact.ContactId

这将返回每种类型用户的行。因此Required用户占一行,Optional User等行占一行

这是一小部分数据:

ActivityId  ScheduledStart  OwnerIdName AccountIdName   new_ContactPersonName   Subject new_ColderNotes AccountId   ContactId   SystemUserId    OptionalOwner   OptionalContact OptionalAccount PartyId ParticipationTypeMask   RequiredContact RequiredAccount RequiredOwner   new_BusinessUnit
    f9ca2637-580a-e111-b263-001ec928e97f    11/17/2011 3:00:00 PM   Bob Schulze Surmodics Pharmaceuticals   Jason Kennedy   Sales Visit - Surmodics NULL    NULL    NULL    f69530fc-da00-e111-b263-001ec928e97f    Bob Schulze NULL    NULL    f69530fc-da00-e111-b263-001ec928e97f    7   NULL    NULL    Bob Schulze NULL
    f9ca2637-580a-e111-b263-001ec928e97f    11/17/2011 3:00:00 PM   Bob Schulze Surmodics Pharmaceuticals   Jason Kennedy   Sales Visit - Surmodics NULL    NULL    NULL    f69530fc-da00-e111-b263-001ec928e97f    Bob Schulze NULL    NULL    f69530fc-da00-e111-b263-001ec928e97f    9   NULL    NULL    Bob Schulze NULL
    f9ca2637-580a-e111-b263-001ec928e97f    11/17/2011 3:00:00 PM   Bob Schulze Surmodics Pharmaceuticals   Jason Kennedy   Sales Visit - Surmodics NULL    c629fb14-1101-e111-b263-001ec928e97f    NULL    NULL    NULL    NULL    Surmodics Pharmaceuticals   c629fb14-1101-e111-b263-001ec928e97f    5   NULL    Surmodics Pharmaceuticals   NULL    NULL
    f9ca2637-580a-e111-b263-001ec928e97f    11/17/2011 3:00:00 PM   Bob Schulze Surmodics Pharmaceuticals   Jason Kennedy   Sales Visit - Surmodics NULL    c629fb14-1101-e111-b263-001ec928e97f    NULL    NULL    NULL    NULL    Surmodics Pharmaceuticals   c629fb14-1101-e111-b263-001ec928e97f    8   NULL    Surmodics Pharmaceuticals   NULL    NULL

正如您所看到的那样ActivityIDParticipationTypeMasks不同ParticipationMask则为5,7,9。

在创建报告时使用所有这些,我得到这样的结果:

enter image description here

为每个ParticipationMask创建一行。我想要做的就是这样做,如果ParticipationMask是1,2或3,那么这些名字进入Sales列,如果它是4,5,6,那么它进入Other Column并且只有一个每个活动的行,而不是每{{1}}个行。无论如何要做到这一点?我被卡住了。我愿意在SQL或SSRS中这样做。

谢谢!

3 个答案:

答案 0 :(得分:1)

这是一个黑暗中的镜头,因为我们并不真正了解您的数据,但如果您喜欢现有的查询,则可以简单地使用它两次但是使用where子句如下:

SELECT
-- Common stuff?
ISNULL(Sales.ActivityId, Other.ActivityId), ISNULL(Sales.ScheduledStart, Other.ScheduledStart), ISNULL(Sales.OwnerIdName, Other.OwnerIdName), ISNULL(Sales.AccountIdName, Other.AccountIdName), ISNULL(Sales.new_ContactPersonName, Other.new_ContactPersonName), ISNULL(Sales.[Subject], Other.[Subject]), ISNULL(Sales.new_ColderNotes, Other.new_ColderNotes)
-- Sales stuff?
, Sales.AccountId, Sales.ContactId, Sales.SystemUserId, Sales.OptionalOwner, Sales.OptionalContact, Sales.OptionalAccount, Sales.PartyId, Sales.ParticipationTypeMask, Sales.RequiredContact, Sales.RequiredAccount, Sales.RequiredOwner, Sales.new_BusinessUnit
-- Other Stuff?
, Other.AccountId, Other.ContactId, Other.SystemUserId, Other.OptionalOwner, Other.OptionalContact, Other.OptionalAccount, Other.PartyId, Other.ParticipationTypeMask, Other.RequiredContact, Other.RequiredAccount, Other.RequiredOwner, Other.new_BusinessUnit
FROM
(
    SELECT DISTINCT 
        Appointment.ActivityId, Appointment.ScheduledStart, Appointment.OwnerIdName, Contact.AccountIdName, Appointment.new_ContactPersonName, 
            Appointment.Subject, Appointment.new_ColderNotes, Account.AccountId, Contact_1.ContactId, SystemUser.SystemUserId, SystemUser.FullName AS OptionalOwner, 
            Contact_1.FullName AS OptionalContact, Account.Name AS OptionalAccount, ActivityParty.PartyId, ActivityParty.ParticipationTypeMask, 
            Contact_1.FullName AS RequiredContact, Account.Name AS RequiredAccount, SystemUser.FullName AS RequiredOwner, Account.new_BusinessUnit
    FROM
        Contact AS Contact_1 RIGHT OUTER JOIN
            Account RIGHT OUTER JOIN
            SystemUser RIGHT OUTER JOIN
            Appointment INNER JOIN
            ActivityParty ON Appointment.ActivityId = ActivityParty.ActivityId ON SystemUser.SystemUserId = ActivityParty.PartyId ON Account.AccountId = ActivityParty.PartyId ON
            Contact_1.ContactId = ActivityParty.PartyId LEFT OUTER JOIN
            Contact ON Appointment.new_ContactPerson = Contact.ContactId
    -- Limit this part to Sales?
    WHERE ParticipationTypeMask BETWEEN 1 AND 3
) as Sales
FULL OUTER JOIN
(
    SELECT DISTINCT 
        Appointment.ActivityId, Appointment.ScheduledStart, Appointment.OwnerIdName, Contact.AccountIdName, Appointment.new_ContactPersonName, 
            Appointment.Subject, Appointment.new_ColderNotes, Account.AccountId, Contact_1.ContactId, SystemUser.SystemUserId, SystemUser.FullName AS OptionalOwner, 
            Contact_1.FullName AS OptionalContact, Account.Name AS OptionalAccount, ActivityParty.PartyId, ActivityParty.ParticipationTypeMask, 
            Contact_1.FullName AS RequiredContact, Account.Name AS RequiredAccount, SystemUser.FullName AS RequiredOwner, Account.new_BusinessUnit
    FROM
        Contact AS Contact_1 RIGHT OUTER JOIN
            Account RIGHT OUTER JOIN
            SystemUser RIGHT OUTER JOIN
            Appointment INNER JOIN
            ActivityParty ON Appointment.ActivityId = ActivityParty.ActivityId ON SystemUser.SystemUserId = ActivityParty.PartyId ON Account.AccountId = ActivityParty.PartyId ON
            Contact_1.ContactId = ActivityParty.PartyId LEFT OUTER JOIN
            Contact ON Appointment.new_ContactPerson = Contact.ContactId
    -- Limit this part to Other?
    WHERE ParticipationTypeMask BETWEEN 4 AND 6
) AS Other ON Sales.ActivityId = Other.ActivityId -- More cols for join?

答案 1 :(得分:0)

一种方法是两次加入您的表,并将ParticipationMask过滤器添加到Join子句。例如

  JOIN activityparty activityparty_sales
    ON appointment.activityid = activityparty_sales.activityid 
    AND activityparty_sales.participationtypemask IN ( 1, 2, 3 ) 

   JOIN activityparty activityparty_other 
     ON appointment.activityid = activityparty_other.activityid 
     AND activityparty_other.participationtypemask IN ( 4, 5, 6 )

这有点复杂(对我来说至少)因为你有一堆Right joins嵌套连接。

我将它们转换为更标准的连接(但没有能力测试我可能是错的)

SELECT [your fields] 
FROM   appointment 
       INNER JOIN activityparty activityparty_sales 
         ON appointment.activityid = activityparty_sales.activityid 
            AND activityparty_sales.participationtypemask IN ( 1, 2, 3 ) 
       LEFT JOIN systemuser systemuser_sales 
         ON systemuser_sales.systemuserid = activityparty_sales.partyid 
       LEFT JOIN ACCOUNT account_sales 
         ON account_sales.accountid = activityparty_sales.partyid 
       LEFT JOIN contact AS contact_1_sales 
         ON contact_1_sales.contactid = activityparty_sales.partyid 
       LEFT OUTER JOIN contact contact_sales 
         ON appointment.new_contactperson = contact_sales.contactid 

       INNER JOIN activityparty activityparty_other 
         ON appointment.activityid = activityparty_other.activityid 
            AND activityparty_other.participationtypemask IN ( 4, 5, 6 ) 
       LEFT JOIN systemuser systemuser_other 
         ON systemuser_other.systemuserid = activityparty_other.partyid 
       LEFT JOIN ACCOUNT account_other 
         ON account_other.accountid = activityparty_other.partyid 
       LEFT JOIN contact AS contact_1_other 
         ON contact_1_other.contactid = activityparty_other.partyid 
       LEFT OUTER JOIN contact contact_other 
         ON appointment.new_contactperson = contact_other.contactid 

另一件让您感到困惑的事情是,在不知道您的数据可能包含SalesOther

的多个值的情况下

如果是这种情况,那么你需要添加两个使用Row_Number的CTE,然后添加一个where子句

WHERE 
 (CTE_sales.activityid  is null 
   or CTE_other.activityid  is null 
    or CTE_sales.RN = CTE_other.RN)

*实际上CTE并不是个坏主意

答案 2 :(得分:-1)

如果我正确地解释您的问题,听起来您需要使用子查询。

编写一个子查询以查找活动的“销售”数据,另一个查找活动的“其他”数据。然后,您可以将每个连接回基本活动记录。请注意,根据数据的确切结构,子查询可以像在连接中添加AND子句一样简单,只需将其过滤到所需的记录类型,然后使用不同的条件重复连接。

这应该可以正常运行,假设活动的每种记录类型只有一种,如果你开始遇到子查询每个活动可以返回多行的情况,那么你可能会遇到问题,它会在尝试时添加额外的行匹配所有可能的组合。