SQL getting multiple columns into one column

a 夏天 提交于 2020-01-04 09:03:16

问题


I have this query that I am using to create a report:

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

This returns rows for each type of User. So one row for Required user and one row for Optional User etc.

This is a small sample of data:

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

As you can see they are the same ActivityID but have different ParticipationTypeMasks those are the 5, 7 , 9.

Using all this when I create a report I get something like this:

It creates a row for each ParticipationMask. What I am trying to do is making it so if the ParticipationMask is 1, 2, or 3 those names go into the Sales column and if it is 4, 5, 6 it goes in the Other Column and only have one row per activity, not one per ParticipationMask. Anyway to do this? I'm stuck. I'm open to doing it in SQL or SSRS.

Thanks!


回答1:


One way is to join to your table twice and add the ParticipationMask filters to the Join Clause. e.g

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

And

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

This is somewhat complicated (for me at least) because you've got a bunch of Right joins with nested joins.

I converted them into more standard joins (but without an ability to test I could be wrong)

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 

Another thing that complicates this is that without knowing your data may have multiple values for Sales and Other

If that's the case then you'll need to add two CTEs that use Row_Number and then Add a where clause

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

*Actually a CTE isn't a bad idea




回答2:


This is a shot in the dark because we don't really know your data, but if you like your existing query it may be possible to simply use it twice but with a where clause like so:

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?



回答3:


If I am interpreting your question correctly it sounds like you need to use sub queries.

Write one sub query to find the “Sales” data for the activity and another to find your “Other” data for the activity. You can then join each one back to the base activity record. Note that depending on exactly how your data is structured the sub queries could be as simple as adding an AND clause to the join which filters it down to just the desired record types, and then repeating the join with different criteria.

This should work assuming there is only one of each record type for the activity, if you start running into situations where a sub query can return more than one row per activity then you may have problems with it breeding extra rows while it tries to match up all of the possible combinations.



来源:https://stackoverflow.com/questions/8433794/sql-getting-multiple-columns-into-one-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!