How do I use a table name that's returned in a select statement, in a join? - sql

*Note: This is not the same as the "possible duplicate". Here, the table name will be different for each record returned in the SELECT statement. So I can't just "set" a variable like set #tableName = 'whatever'.
Here's my SQL - take a look at my last inner join. e.Name from the table EmailSendDefintion is the name of the table I need to join to. So, this is kind of dynamic, I know, but how do I join to a table that is stored in a field in another table?
select top 5000
x.HL_ACCT_ID as 'HL_ACCT_ID',
x.SALE_CODE as 'SALE_CODE',
s.SubscriberKey as 'EmailAddress',
o.EventDate as 'Opened',
c.EventDate as 'Clicked',
b.EventDate as 'Bounced'
from c100._sent s with (nolock)
inner join c100._job j with (nolock) on s.jobid = j.jobid
inner join emailsenddefinition e with (nolock) on e.customerkey = j.emailsenddefinition
left join c100._open o with (nolock) on o.jobid = s.jobid and o.subscriberkey = s.subscriberkey
left join c100._click c with (nolock) on c.jobid = s.jobid and c.subscriberkey = s.subscriberkey
left join c100._bounce b with (nolock) on b.jobid = s.jobid and b.subscriberkey = s.subscriberkey
inner join c100.[e.name] x with (nolock) on x.EmailAddress = s.SubscriberKey
where e.clientid = 100

Perhaps you could just create a view that outputs the union of all the e.name tables? Then join to the view.
In order to keep this short, let's say you have just 2 different tables whose name could be in the e.name column, SubscriberEmail1 and SubscriberEmail2.
Then you could create a view like this:
CREATE VIEW SubscriberEmailUnion
AS
SELECT
'SubscriberEmail1' as TableName,
HL_ACCT_ID,
SALE_CODE,
EmailAddress
FROM SubscriberEmail1
UNION
SELECT
'SubscriberEmail2' as TableName,
HL_ACCT_ID,
SALE_CODE,
EmailAddress
FROM SubscriberEmail2
GO
Note that each part of the view is adding the name of it's underlying table as a column. You can then change your final join to:
inner join SubscriberEmailUnion x with (nolock) on (
x.EmailAddress = s.SubscriberKey
AND x.TableName = e.Name
)
I'm personally most familiar with MS Sql Server so my sample uses that syntax. Should be easy enough to change to work with a different server if necessary though.
For performance you can then use whatever feature your DB has, indexed views etc.

How many tables do you have? If not too many one option would be to left join all of them
left join c100.table1 x1 on x1.EmailAddress = s.SubscriberKey and [e.name] = 'table1'
left join c100.table2 x1 on x2.EmailAddress = s.SubscriberKey and [e.name] = 'table2'
etc...
and then in the select
coalesce(x1.HL_ACCT_ID, x2.HL_ACCT_ID, etc...) as 'HL_ACCT_ID',

Related

How to create distinct count from queries with several tables

I am trying to create one single query that will give me a distinct count for both the ActivityID and the CommentID. My query in MS Access looks like this:
SELECT
tbl_Category.Category, Count(tbl_Activity.ActivityID) AS CountOfActivityID,
Count(tbl_Comments.CommentID) AS CountOfCommentID
FROM tbl_Category LEFT JOIN
(tbl_Activity LEFT JOIN tbl_Comments ON
tbl_Activity.ActivityID = tbl_Comments.ActivityID) ON
tbl_Category.CategoryID = tbl_Activity.CategoryID
WHERE
(((tbl_Activity.UnitID)=5) AND ((tbl_Comments.PeriodID)=1))
GROUP BY
tbl_Category.Category;
I know the answer must somehow include SELECT DISTINCT but am not able to get it to work. Do I need to create multiple subqueries?
This is really painful in MS Access. I think the following does what you want to do:
SELECT ac.Category, ac.num_activities, aco.num_comments
FROM (SELECT ca.category, COUNT(*) as num_activities
FROM (SELECT DISTINCT c.Category, a.ActivityID
FROM (tbl_Category as c INNER JOIN
tbl_Activity as a
ON c.CategoryID = a.CategoryID
) INNER JOIN
tbl_Comments as co
ON a.ActivityID = co.ActivityID
WHERE a.UnitID = 5 AND co.PeriodID = 1
) as caa
GROUP BY ca.category
) as ca LEFT JOIN
(SELECT c.Category, COUNT(*) as num_comments
FROM (SELECT DISTINCT c.Category, co.CommentId
FROM (tbl_Category as c INNER JOIN
tbl_Activity as a
ON c.CategoryID = a.CategoryID
) INNER JOIN
tbl_Comments as co
ON a.ActivityID = co.ActivityID
WHERE a.UnitID = 5 AND co.PeriodID = 1
) as aco
GROUP BY c.Category
) as aco
ON aco.CommentId = ac.CommentId
Note that your LEFT JOINs are superfluous because the WHERE clause turns them into INNER JOINs. This adjusts the logic for that purpose. The filtering is also very tricky, because it uses both tables, requiring that both subqueries have both JOINs.
You can use DISTINCT:
SELECT
tbl_Category.Category, Count(DISTINCT tbl_Activity.ActivityID) AS CountOfActivityID,
Count(DISTINCT tbl_Comments.CommentID) AS CountOfCommentID
FROM tbl_Category LEFT JOIN
(tbl_Activity LEFT JOIN tbl_Comments ON
tbl_Activity.ActivityID = tbl_Comments.ActivityID) ON
tbl_Category.CategoryID = tbl_Activity.CategoryID
WHERE
(((tbl_Activity.UnitID)=5) AND ((tbl_Comments.PeriodID)=1))
GROUP BY
tbl_Category.Category;

Putting the results of a query into new table in SQL Server

I want to insert query results into new table is there any way I can make changes in code so that it gets stored in a table.
My query:
SELECT DISTINCT TOP 5 a.DocEntry
,b.TrgetEntry
,b.itemcode
,a.DocNum AS 'Order No.'
,a.CardCode
,a.CardName
,b.DocDate AS [Delivery No.]
,c.targettype AS 'Ctargettype'
,c.trgetentry AS 'Ctargetentry'
,c.itemcode AS 'c-itemcode'
,c.docentry AS 'Cdocentry' a.CancelDate
,a.Project
,a.DocStatus
,b.ObjType
,a.ObjType
FROM ORDR a
INNER JOIN rdr1 b ON a.DocEntry = b.DocEntry
LEFT JOIN dln1 c ON c.TrgetEntry = b.DocEntry
AND b.itemcode = c.ItemCode order by c.itemcode;
You can do it as it will create a new table and insert the records into that table. If you have already created table then you can give name and individual columns also for both insertion and selection.
SELECT *
INTO YourTableName
FROM (
SELECT DISTINCT TOP 5 a.DocEntry
,b.TrgetEntry
,b.itemcode
,a.DocNum AS 'Order No.'
,a.CardCode
,a.CardName
,b.DocDate AS [Delivery No.]
,c.targettype AS 'Ctargettype'
,c.trgetentry AS 'Ctargetentry'
,c.itemcode AS 'c-itemcode'
,c.docentry AS 'Cdocentry' a.CancelDate
,a.Project
,a.DocStatus
,b.ObjType
,a.ObjType
FROM ORDR a
INNER JOIN rdr1 b ON a.DocEntry = b.DocEntry
LEFT JOIN dln1 c ON c.TrgetEntry = b.DocEntry
AND b.itemcode = c.ItemCode
)
a
For using order by clause you can try something like this.
SELECT DISTINCT
Insured_Customers.FirstName, Insured_Customers.LastName,
Insured_Customers.YearlyIncome, Insured_Customers.MaritalStatus
INTO Fast_Customers from Insured_Customers INNER JOIN
(
SELECT * FROM CarSensor_Data where Speed > 35
) AS SensorD
ON Insured_Customers.CustomerKey = SensorD.CustomerKey
ORDER BY YearlyIncome;
You can learn in detail about INTO Clause Here
This looks like SQL Server code. In that database, you add into after the select clause:
Select distinct top 5 o.DocEntry, r.TrgetEntry, r.itemcode, o.DocNum as order_num, o.CardCode,
o.CardName, r.DocDate as delivery_num,
d.targettype as Ctargettype, d.trgetentry as Ctargetentry,
d.itemcode as c_itemcode, d.docentry as Cdocentry
a.CancelDate,a.Project, a.DocStatus,b.ObjType,a.ObjType
into <new table>
from ORDR o inner join
rdr1 r
On o.DocEntry = r.DocEntry left join
dln1 d
on d.TrgetEntry = r.DocEntry and
d.itemcode = r.ItemCode;
Note that I changed the table aliases so they are meaningful. Arbitrary letters are very hard to follow. Table abbreviations are more useful.
I also changed the column aliases so they do not need to be escaped. Do not make troublesome aliases!

How to replace only some Guids from a table to another, under conditions

I've created a View, but I wanted to change some of the result's Guids to Guids from another table, I want it directly in my view Result and I Don't know how?
select p.[Guid], c.[Guid] detailsGuid
INTO #temp1
from
ret_PayrollCalculationCommands s INNER JOIN
ret_PayrollCalculations p ON p.CalculationCommandGuid = s.Guid INNER JOIN
ret_vwPayrollCalculationDetails c ON c.CalculationGuid = p.Guid
you should INNER JOIN your table with same table that has target Guid column with another condition:
SELECT
p.[Guid],
c.[Guid] detailsGuid,
pMainCalculation.[Guid] AS [TargetGuid]
INTO #temp1
FROM
ret_PayrollCalculationCommands s INNER JOIN
ret_PayrollCalculations p ON p.CalculationCommandGuid = s.Guid INNER JOIN
ret_PayrollCalculations pMainCalculation ON pMainCalculation.CalculationCommandGuid = p.CalculationCommandGuid AND pMainCalculation.MainCalculation = 1 INNER JOIN
ret_vwPayrollCalculationDetails c ON c.CalculationGuid = p.Guid

How to select multiple many to many in relation with a single table

I'm currently working with database, but I've got stuck with a select query.
However, I'm not database expert.
The query should return the data from a table that has two relationships of many to many.
This is my tables Diagram that would shows the concept of my question
The Select Query should View three columns, which are VidTbl.Name, ActorTbl.Name and SubTitelTbl.name.
So, I've read and search in the Internet and I've given tries
First try
SELECT
VidTbl.NAME AS Video_Titel_Name,
ActorTbl.NAME AS Actor_Name
FROM ActorInVid
INNER JOIN VidTbl
ON VidTbl.Id = ActorInVid.FKVidId
INNER JOIN ActorTbl
ON ActorTbl.Id = ActorInVid.FKActorId
UNION all
SELECT
VidTbl.NAME AS Video_Titel_Name,
SubTitelTbl.NAME AS SubTitel_Langu
FROM SubTitelInVid
INNER JOIN VidTbl
ON VidTbl.Id = SubTitelInVid.FKVidId
INNER JOIN SubTitelTbl
ON SubTitelTbl.Id = SubTitelInVid.FKSTId
The Result I've got, it was wrong
Then I tried another way to solve this problem, but again I've got another error
second try
SELECT Temp1.*
From (SELECT VidTbl.Id AS Video_Id,
VidTbl.NAME AS Video_Titel_Name,
ActorTbl.NAME AS Actor_Name
FROM ActorInVid
INNER JOIN VidTbl
ON VidTbl.Id = ActorInVid.FKVidId
INNER JOIN ActorTbl
ON ActorTbl.Id = ActorInVid.FKActorId) AS Temp1
SELECT Temp2.*
FROM (SELECT VidTbl.Id AS Video_Id,
SubTitelTbl.NAME AS SubTitel_Langu
FROM SubTitelInVid
INNER JOIN VidTbl
ON VidTbl.Id = SubTitelInVid.FKVidId
INNER JOIN SubTitelTbl
ON SubTitelTbl.Id = SubTitelInVid.FKSTId) AS Temp2
SELECT *
FROM VidTbl
INNER JOIN Temp1
on Temp1.Video_Id = VidTbl.Id
INNER JOIN Temp2
on Temp2.Video_Id = VidTbl.Id
The error, I've got in the last select that was wrong
Thanks a lot for your help any ways
I wish that my question is clear and useful
Thanks again.
You are close. This should work...
SELECT
VidTbl.Name,
ActorTbl.Name,
SubTitelTbl.name
FROM VidTbl
INNER JOIN ActorInVid ON VidTbl.Id = ActorInVid.FKVidId
INNER JOIN ActorTbl ON ActorTbl.Id = ActorInVid.FKActorId
INNER JOIN SubTitelInVid ON VidTbl.Id = SubTitelInVid.FKVidId
INNER JOIN SubTitelTbl ON SubTitelTbl.Id = SubTitelInVid.FKSTId
SELECT DISTINCT vt.Name, at.Name, st.Name
FROM VidTbl vt
JOIN ActionInVid aiv ON aiv.VidId = vt.Id
JOIN SubtitleInVid siv ON siv.VidId = vt.Id
JOIN ActorTbl at ON at.Id = aiv.ActorId
JOIN SubTitleTbl st ON st.Id = siv.STId

EXIST SQL Simplify

-- Insert statements for procedure here
IF EXISTS
(SELECT S.SCHEDULER_ID FROM Scheduler S WITH (NOLOCK)
INNER JOIN CaseDetails_Scheduler_Mapping CDSM WITH (NOLOCK) ON (S.SCHEDULER_ID=CDSM.SCHEDULER_ID)
INNER JOIN CaseDetails CD WITH (NOLOCK) ON (CDSM.CASE_DETAIL_ID = CD.CASE_DETAIL_ID)
WHERE S.HEARD_BEFORE_ID=#HEARD_BEFORE_ID AND S.SCHEDULE_START_TIME=#SCHEDULE_START_TIME AND S.SCHEDULE_DATE=#SCHEDULE_DATE)
BEGIN
SELECT '4' AS 'STATUS', (SELECT S.SCHEDULER_ID FROM Scheduler S WITH (NOLOCK)
INNER JOIN CaseDetails_Scheduler_Mapping CDSM WITH (NOLOCK) ON (S.SCHEDULER_ID=CDSM.SCHEDULER_ID)
INNER JOIN CaseDetails CD WITH (NOLOCK) ON (CDSM.CASE_DETAIL_ID = CD.CASE_DETAIL_ID)
WHERE S.HEARD_BEFORE_ID=#HEARD_BEFORE_ID AND S.SCHEDULE_START_TIME=#SCHEDULE_START_TIME AND S.SCHEDULE_DATE=#SCHEDULE_DATE) AS 'SCHEDULER_ID',
(SELECT CD.CASE_NO FROM Scheduler S WITH (NOLOCK)
INNER JOIN CaseDetails_Scheduler_Mapping CDSM WITH (NOLOCK) ON (S.SCHEDULER_ID=CDSM.SCHEDULER_ID)
INNER JOIN CaseDetails CD WITH (NOLOCK) ON (CDSM.CASE_DETAIL_ID = CD.CASE_DETAIL_ID)
WHERE S.HEARD_BEFORE_ID=#HEARD_BEFORE_ID AND S.SCHEDULE_START_TIME=#SCHEDULE_START_TIME AND S.SCHEDULE_DATE=#SCHEDULE_DATE) AS 'CASE_NO'
END
I know this code are correct , but is there a way to simplify my sql code? i try did select 2 column in 1 table but it will appear "Only one expression can be specified in the select list when the subquery is not introduced with EXISTS" error..... Sorry if i asking such beginner question..
I think you can remove the IF EXISTS part. Here is a simplified version of your THEN part:
SELECT
'4' AS [STATUS],
S.SCHEDULER_ID AS [SCHEDULER_ID],
CD.CASE_NO AS [CASE_NO]
FROM Scheduler S WITH (NOLOCK)
INNER JOIN CaseDetails_Scheduler_Mapping CDSM WITH (NOLOCK)
ON (S.SCHEDULER_ID = CDSM.SCHEDULER_ID)
INNER JOIN CaseDetails CD WITH (NOLOCK)
ON (CDSM.CASE_DETAIL_ID = CD.CASE_DETAIL_ID)
WHERE
S.HEARD_BEFORE_ID = #HEARD_BEFORE_ID
AND S.SCHEDULE_START_TIME = #SCHEDULE_START_TIME
AND S.SCHEDULE_DATE = #SCHEDULE_DATE
Note that putting NOLOCK everywhere is considered a bad habit.