问题
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