Use while to select a set of tables using id - sql-server

I am using SQL Server 2012 and want to translate this into T-SQL code:
Get a set of IDs from some table. i.e.: select id from id_table where id > 3.
Use these IDs as input to another query, for example:
SELECT count(*) nb , [status]
FROM [tbl_dest] as dest with (nolock)
inner join [tbl_messages] as source with (nolock)
on dest.message_id=source.id
where source.id=338
I want to use the second query using the IDs that I got from the first query in the last where clause is where source.id=338 using a loop or a variable etc.
Can you please help with your knowledge?

One straightforward option here would be to use a WHERE IN clause:
SELECT
COUNT(*) nb,
[status]
FROM [tbl_dest] AS dest WITH (NOLOCK)
INNER JOIN [tbl_messages] AS source WITH (NOLOCK)
ON dest.message_id = source.id
WHERE source.id IN (SELECT id FROM id_table WHERE id > 3);
We can also rephrase the WHERE IN using another join:
SELECT
COUNT(*) nb,
[status]
FROM [tbl_dest] AS dest WITH (NOLOCK)
INNER JOIN [tbl_messages] AS source WITH (NOLOCK)
ON dest.message_id = source.id
INNER JOIN id_table it
ON source.id = it.id
WHERE it.id > 3;

Cursor is not required. Just try to use subquery;
SELECT count(*) nb , [status] FROM [tbl_dest] as dest with (nolock) inner join
[tbl_messages] as source with (nolock) on
dest.message_id=source.id where source.id IN (select id from id_table where id >3)

Related

Using sub-queries and filter in WHERE clause while joining tables

SELECT DISTINCT(t1.Ticker),t2.SecurityID,t2.ClosePrice,t2.QuoteDateTime FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2
ON t2.SecurityID =t1.SecurityID
WHERE t2.QuoteDateTime IN (SELECT max(QuoteDateTime) FROM [Hub].[SecurityMaster].[SecurityPrices]) AND t1.SecurityTypeName = 'REIT'
I get an output with no data. The subquery doesn't run along with the other filter in the WHERE clause. I am not sure what I am doing wrong. Can somebody please help!
If you are trying to get the lastest row from SecurityPrices for each Ticker, one option is to use cross apply():
select --distinct /* distinct not needed if `Ticker` is unique on `smd`
smd.Ticker
, sp.SecurityID
, sp.ClosePrice
, sp.QuoteDateTime
from [Hub].[SecurityMaster].[SecurityMasterDetails] as smd
cross apply (
select top 1
i.SecurityID
, i.ClosePrice
, i.QuoteDateTime
from [Hub].[SecurityMaster].[SecurityPrices] i
where i.SecurityID = smd.SecurityID
order by i.QuoteDateTime desc
) as sp
where SecurityTypeName = 'REIT' /* which table does this column belong to? */
I think your query would be
SELECT DISTINCT TOP 1 WITH TIES
t1.Ticker,
t2.SecurityID,
t2.ClosePrice,
t2.QuoteDateTime
FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2 ON t2.SecurityID =t1.SecurityID
WHERE SecurityTypeName = 'REIT'
ORDER BY t2.QuoteDateTime DESC
You aren't getting results because the max(QuoteDateTime) record doesn't have SecurityTypeName = 'REIT'. I think you want the max(QuoteDateTime) for this SecurityTypeName, so this can be done with an INNER JOIN.
SELECT DISTINCT
(t1.Ticker),
t2.SecurityID,
t2.ClosePrice,
t2.QuoteDateTime
FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2
ON t2.SecurityID =t1.SecurityID
INNER JOIN
(SELECT max(QuoteDateTime) DT FROM [Hub].[SecurityMaster].[SecurityPrices]) P on P.DT = t2.QuoteDateTime
WHERE SecurityTypeName = 'REIT'
EDIT
Your data doesn't have what you think it does, I suspect. Here is how you can check...
--Find the SecurityID that matches the max date
SELECT
SecurityID ,
max(QuoteDateTime) DT
FROM [Hub].[SecurityMaster].[SecurityPrices]
GROUP BY SecurityID
--I'm betting this ID isn't in your SecurityMasterDetails where the Type is REIT
SELECT DISTINCT
SecurityID
FROM SecurityMasterDetails
WHERE SecurityTypeName = 'REIT'
Since the SecurityID returned in the first query isn't in the second query result set, you are going to get NULL results.

Update from CTE does not update properly all table rows. But updates all existing table rows with CTE values returned in the first ID in CTE resultset

I've buit a CTE and want to update an existing physical table based on results from the CTE.
;WITH CTE
AS
(
Select t.ID As [CTE_ID]
,count(distinct case when e.Department='M' then t.ID else null end) as M_Marketing
,count(distinct case when e.Department='S' then t.ID else null end) as S_Sales
,count(distinct case when e.Department='U' then t.ID else null end) as U_Utilization
,count(distinct case when e.Department=' ' then t.ID else null end) as No_NoDepartment
From dbo.Table t (nolock)
Left Join dbo.ClearedEmployee ce (nolock) ON t.ID = ce.building_fk
Join dbo.Employee e (nolock) ON ce.employee_fk = e.employee_pk
Group By t.ID
)
Select *, t.ID
From CTE c (nolock)
FULL JOIN dbo.Table t (nolock) ON t.ID=c.[CTE_ID]
Order By t.ID ASC;
I want to updated my existing table with the results produced BY THE CODE ABOVE for each ID within the CTE And I'm using the code below:
UPDATE dbo.Table t
SET Marketing=M_Marketing,
Sales=S_Sales,
Utilization=U_Utilization,
NoDepartment=No_NoDepartment
FROM CTE
But this code updates all rows (all rows with unique IDs) of Marketing, Sales, Utilization and NoDepartment columns with values that present in the first row of the CTE result set. Basicaly I cannot really use CTE true result set to update the table.
UPDATE t
SET t.Marketing=M_Marketing,
t.Sales=S_Sales,
t.Utilization=U_Utilization,
t.NoDepartment=No_NoDepartment
FROM CTE C JOIN Table T ON T.ID=C.CTE_ID
In your update statement, you need to tell SQL Server how to map the data from the CTE to the data from the table.

Applying outer layer that wrapping two select statement

I have two query which has successfully inner join
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
The above query will return me the name and the corresponding number of count and the sum. I need to do a comparison between the count and sum. If the count doesnt match the sum, it will return 0, else 1. And so my idea was implementing another outer layer to wrap them up and use CASE WHEN. However, I've failed to apply an outer layer just to wrap them up? This is what I've tried:
select * from(
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
)
Alright the problem can be solved by simply assigning a name to the outer layer.
select * from(
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
) as whatever //SQL Server need a name to wrap
Hope it will help any newbie like me
Ok, so far you have selected everything your first select has generated (kinda useless, but a start for what you want ;) )
SELECT CASE
WHEN countresult=sumresult THEN 'Equal'
ELSE 'Not'
END
FROM ( --your join select --
)
I don't have any sample data to test this so can just go on your code.
Your queries for t1 & t2 look identical - why don't you just do a sum & count in 1 step?
SELECT COUNT(column) AS countResult
,SUM(column) AS sumResult
FROM tableA INNER JOIN tableB
ON tableA.id = tableB.id
GROUP BY name
Also, as you mention you are a newb - read up on Common Table Expressions in SQL Server.
Before SQL 2005 you had to write these convoluted queries within queries within...
Get into the habit of using CTEs now.

Stored procedure inner join

My first stored procedure (in sql-server). I'm not able to make it work, it raises a warning in a.Id
After reading, and not really understand much, I'm not even sure if I can use this inner join inside a stored procedure.
select top 1 b.*, a.*
FROM Bids b
INNER JOIN Auctions a
ON b.Auction_Id = a.Id
(NOLOCK) WHERE ( a.Ends IS NOT NULL AND a.Starts IS NOT NULL AND a.Starts < #Now AND a.Ends > #Now)
ORDER BY b.CreationTime DESC
Actually, I'll need just b.* but I assume I have to retrieve all the fields?.
Thanks
Change the locking hint to this:
INNER JOIN Auctions a WITH(NOLOCK)
Full query would be:
select top 1 b.*, a.*
FROM Bids b
JOIN Auctions a WITH(NOLOCK) ON b.Auction_Id = a.Id
WHERE ( a.Ends IS NOT NULL
AND a.Starts IS NOT NULL
AND a.Starts < #Now
AND a.Ends > #Now)
ORDER BY b.CreationTime DESC
Take the (Nolock) out, or put it after the table name if you need it.
You can use Select to select any fields you want from any table in your query.

Applying distinct to single column

I have a sql query
select distinct
Process.ReportLogProcessID as [Process.ReportLogProcessID],
Process.ProcessTitle as [Process.ProcessTitle],
CAST(User0.PrimaryEmail AS nvarchar(max)) as [Process_Contacts.IsPrimaryContact]
from
ReportProcess as Process inner join
ReportProcessContact as ReportProcessContact0 on
((ReportProcessContact0.SessionID = Process.SessionID)) left outer join
[User] as User0 on
((ReportProcessContact0.ReferenceID = User0.UserID)) left outer join
[Group] as Group0 on
((ReportProcessContact0.ReferenceID = Group0.GroupID and
ReportProcessContact0.ReferenceType = 2))
order by
[Process.ProcessTitle] asc
and it give below result
if you see it returns two rows with the same 'Process Title'-'Testing123' is there any way I can distinct this in spite of whatever be the 'Process Contact'.
Is there any way to distinct the result on the base of particular column?
In your query [Process_Contacts.IsPrimaryContact] column have different emails for both records. If you remove that column then only it will distinct records.
UPDATE : You can try like :
select
Process.ReportLogProcessID as [Process.ReportLogProcessID],
Process.ProcessTitle as [Process.ProcessTitle],
MAX(CAST(User0.PrimaryEmail AS nvarchar(max))) as [Process_Contacts.IsPrimaryContact]
from ReportProcess as Process
inner join ReportProcessContact as ReportProcessContact0 on
((ReportProcessContact0.SessionID = Process.SessionID))
left outer join [User] as User0 on
((ReportProcessContact0.ReferenceID = User0.UserID))
left outer join [Group] as Group0 on
((ReportProcessContact0.ReferenceID = Group0.GroupID and
ReportProcessContact0.ReferenceType = 2))
group by Process.ReportLogProcessID, Process.ProcessTitle
order by [Process.ProcessTitle] asc

Resources