check existance of every value in IN statement - sql-server

I have a query like below. What i want is to select null or blank if there is no records for a particular value in the IN statement.
There values are entered by user.
select system_code, max(last_update_timestamp) as [last_update_timestamp]
from table_name
where system_code in ('E1','E2','E3')
Group by system_code
E1 has 100 records
E2 has 20 records
E3 has no records
Using the above query i am getting this result :
Sytem_code last_update_timestamp
E1 '2014-09-28 11:35:10.647'
E2 '2014-09-28 11:35:10.647'
Expected reuslt
Sytem_code last_update_timestamp
E1 '2014-09-28 11:35:10.647'
E2 '2014-09-28 11:35:10.647'
E3 Null or Blank
Any help will be appreciated.

Use Table Value Constructor to build an in-line table containing all values of the IN operator. Then LEFT JOIN your query to this table:
SELECT x.sc, [last_update_timestamp]
FROM (VALUES ('E1'), ('E2'), ('E3')) AS x(sc)
LEFT JOIN (
SELECT system_code, max(last_update_timestamp) as [last_update_timestamp]
FROM table_name
WHERE system_code IN ('E1','E2','E3')
GROUP BY system_code ) AS t ON x.sc = t.system_code
Demo here

SELECT x.sc, max(last_update_timestamp) as [last_update_timestamp]
FROM (VALUES ('E1'), ('E2'), ('E3')) AS x(sc)
LEFT JOIN table_name
ON table_name.system_code = x.sc
GROUP BY x.sc

That query works for most DB engines
select tmp.system_code, max(table_name.last_update_timestamp) as [last_update_timestamp]
from
(
select 'E1' as system_code
union all
select 'E2'
union all
select 'E3'
) tmp
left join table_name on tmp.system_code = table_name.system_code
and table_name.system_code in ('E1','E2','E3')
Group by tmp.system_code

Related

How can I sort concat_ws(';',collect_set(name)) result in hive?

How can I sort result of this query alphabetically?
select b6.S_Architect as S_Architect
from applications a
left outer join
(select id,concat_ws(';' , collect_set(name)) as S_Architect
from solution_architect
group by parentcontentid
) b6 on a.id = b6.Id;
Expected result
Andy;Bravo;Cindy;David
Actual result
Cindy;Bravo;David;Andy
Use sort_array:
select concat_ws('\073',sort_array(collect_set(name))) from (select stack(4,'Cindy','Bravo','David','Andy') as name) s;
Returns:
OK
Andy;Bravo;Cindy;David

SQL COLUMN ERROR for JOIN

I have a Dtltable
tabid TickNUM TickType Amount
001-FGF C2001 Credit 133
001-FGF Tk002 Token 23
001-FGF Tk003 Token 43
Is there anyway, i can pull all the tabid data using single TickNum, coz the tabid is same for all TickNum.
Select * from Dtltable
where tickNum = 'C2001'
but it displays only particluar TickNum row. I need all rows with similar tabid's as well. Not sure how to write logic.
Using a JOIN
SELECT d1.*
FROM Dtltable d1
INNER JOIN Dtltable d2 ON d2.tabid = d1.tabid AND d2.TickNUM = 'C2001'
One method is a subquery:
select d.*
from dtltable d
where d.tabid = (select d2.tabid from dtltable d2 where d2.tickNum = 'C2001');
If the subquery could return more than one row, use in instead of =.
Though this is a bit long, you can achieve this by first selecting distinct data, then by using inner join. Below how I did that.
CReate table #temptab
(
tabid nvarchar(20) null,
ticknum nvarchar(10)null,
ticktype varchar(20)null
)
Create table #temptab1
(
tabid nvarchar(20)null,
ticknum nvarchar(10)null,
ticktype varchar(20)null
)
insert into #temptab1(tabid,ticknum)
select distinct tabid , ticknum from #temptab where ticknum='C2001' // you can pass #param instead of hardcoded value.
//below line, where you will get data:
select t.tabid,t.ticknum,t.ticktype from #temptab1 t1 inner join #temptab t on t1.tabid= t.tabid

SQL Server LEFT OUTER JOIN HAVING criteria restricts results [duplicate]

I have this query in MySQL:
SELECT pr.*, pr7.value AS `room_price_high`
FROM `jos_hp_properties` pr
LEFT OUTER JOIN `jos_hp_properties2` pr7 ON pr7.property=pr.id
WHERE pr7.field=23
The jos_hp_properties table has 27 rows but the query only returns one. Based on this question I think it may be because of the WHERE clause. The jos_hp_properties2 table has fields id, property, field, value, where field is a foreign key to a third table (which I don't need to get data from).
Is there a way to select all the rows from the first table, including the value from table #2 where the field is 23 (or NULL if there is no field 23)?
Sure. Move the WHERE condition to the JOIN:
SELECT pr.*, pr7.value AS `room_price_high`
FROM `jos_hp_properties` pr
LEFT JOIN `jos_hp_properties2` pr7
ON pr7.property=pr.id
AND
pr7.field=23
You must place the pr7 criteria in the join, not in the where clause. The where clause works on the entire result set AFTER the join has been performed.
SELECT pr.*, pr7.value AS `room_price_high`
FROM `jos_hp_properties` pr
LEFT OUTER JOIN `jos_hp_properties2` pr7 ON pr7.property=pr.id and pr7.field=23
Try this:
SELECT pr.*, pr7.value AS `room_price_high`
FROM `jos_hp_properties` pr
LEFT OUTER JOIN `jos_hp_properties2` pr7 ON pr7.property=pr.id
WHERE (pr7.field=23 OR pr7.field is null)
You can also use a CTE (Common Table Expression) to do the select, then use the CTE to do the left join..
wrc (parentid, childid) as (
select parentid, childid
from placechild
where relationshipid in (select id from placerelationship where relationship = 'Winter Region Capital')
),
stw (cnid, coid, capid, st_or_te, sid, scid,wcid) as (
select s.cnid, s.coid, s.capid, s.st_or_te, s.sid, s.scid, w.childid
from stcap s
left join wrc w
on s.sid = w.parentid
)
select * from stw

Duplicate record after joining two tables

I am currently having trouble with my query after joining two tables I am getting duplicated records. What i want to do is get the details from table 1 and the payment record from table 2 with same date.. here is my query.
SELECT dbo.tblautoipekonek.ipno,
dbo.tblautoipekonek.awbno,
dbo.tblautoipekonek.ipamount,
dbo.tblautoipekonek.orno,
dbo.tbladdfunds.username,
dbo.tbladdfunds.newctfbal,
dbo.tbladdfunds.addedctfamt,
dbo.tbladdfunds.oldctfbal,
dbo.tbladdfunds.newipbal,
dbo.tbladdfunds.addedipamt,
dbo.tbladdfunds.oldipbal,
dbo.tbladdfunds.date,
dbo.tblautoipekonek.date AS Expr1
FROM dbo.tblautoipekonek
LEFT OUTER JOIN dbo.tbladdfunds
ON dbo.tblautoipekonek.date = dbo.tbladdfunds.date
WHERE
( dbo.tblautoipekonek.date = '06/06/2014' )
Hi you can use "Distinct" keyword at after "select" keyword. it will get the single record.
Good to replace dbo.tablename with alias name give to tablename as
select
distinct
auto.IPNo, ... ---here you can add other column of this table.
fund.AddedCTFAmt --same thing done here.
FROM tblAutoIPEkonek auto
LEFT OUTER JOIN dbo.tblAddfunds fund
ON auto.Date = fund.Date --try to add more join condition so filteration done here of data which is fastest/
WHERE (auto.Date = '06/06/2014')
SELECT DISTINCT dbo.tblautoipekonek.ipno,
dbo.tblautoipekonek.awbno,
dbo.tblautoipekonek.ipamount,
dbo.tblautoipekonek.orno,
dbo.tbladdfunds.username,
dbo.tbladdfunds.newctfbal,
dbo.tbladdfunds.addedctfamt,
dbo.tbladdfunds.oldctfbal,
dbo.tbladdfunds.newipbal,
dbo.tbladdfunds.addedipamt,
dbo.tbladdfunds.oldipbal,
dbo.tbladdfunds.date,
dbo.tblautoipekonek.date AS Expr1
FROM dbo.tblautoipekonek
LEFT OUTER JOIN dbo.tbladdfunds
ON dbo.tblautoipekonek.date = dbo.tbladdfunds.date
WHERE
( dbo.tblautoipekonek.date = '06/06/2014' )
GROUP BY dbo.tblautoipekonek.ipno,
dbo.tblautoipekonek.awbno,
dbo.tblautoipekonek.ipamount,
dbo.tblautoipekonek.orno,
dbo.tbladdfunds.username,
dbo.tbladdfunds.newctfbal,
dbo.tbladdfunds.addedctfamt,
dbo.tbladdfunds.oldctfbal,
dbo.tbladdfunds.newipbal,
dbo.tbladdfunds.addedipamt,
dbo.tbladdfunds.oldipbal,
dbo.tbladdfunds.date,
dbo.tblautoipekonek.date AS Expr1
Not sure if this will work for you but this is what I would use:
SELECT
p.ipno,
p.awbno,
p.ipamount,
p.orno,
f.username,
f.newctfbal,
f.addedctfamt,
f.oldctfbal,
f.newipbal,
f.addedipamt,
f.oldipbal,
f.date,
p.date Expr1
FROM
dbo.tblautoipekonek p
CROSS APPLY
(
SELECT TOP 1
*
FROM
dbo.tbladdfunds f
WHERE
p.date = f.date
ORDER BY
f.newipbal DESC
) f
This will get you one line from each entry in dbo.tblautoipekonek joined with the matching date entry from dbo.tbladdfunds which has the highest value in newipbal

Join the table valued function in the query

I have one table vwuser. I want join this table with the table valued function fnuserrank(userID). So I need to cross apply with table valued function:
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
For each userID it generates multiple records. I only want the last record for each empid that does not have a Rank of Term(inated). How can I do this?
Data:
HistoryID empid Rank MonitorDate
1 A1 E1 2012-8-9
2 A1 E2 2012-9-12
3 A1 Term 2012-10-13
4 A2 E3 2011-10-09
5 A2 TERM 2012-11-9
From this 2nd record and 4th record must be selected.
In SQL Server 2005+ you can use this Common Table Expression (CTE) to determine the latest record by MonitorDate that doesn't have a Rank of 'Term':
WITH EmployeeData AS
(
SELECT *
, ROW_NUMBER() OVER (PARTITION BY empId, ORDER BY MonitorDate DESC) AS RowNumber
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
WHERE Rank != 'Term'
)
SELECT *
FROM EmployeeData AS ed
WHERE ed.RowNumber = 1;
Note: The statement before this CTE will need to end in a semi-colon. Because of this, I have seen many people write them like ;WITH EmployeeData AS...
You'll have to play with this. Having trouble mocking your schema on sqlfiddle.
Select bar.*
from
(
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
where rank != 'TERM'
) foo
left join
(
SELECT *
FROM vwuser AS b
CROSS APPLY fnuserrank(b.userid)
where rank != 'TERM'
) bar
on foo.empId = bar.empId
and foo.MonitorDate > bar.MonitorDate
where bar.empid is null
I always need to test out left outers on dates being higher. The way it works is you do a left outer. Every row EXCEPT one per user has row(s) with a higher monitor date. That one row is the one you want. I usually use an example from my code, but i'm on the wrong laptop. to get it working you can select foo., bar. and look at the results and spot the row you want and make the condition correct.
You could also do this, which is easier to remember
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
) foo
join
(
select empid, max(monitordate) maxdate
FROM vwuser AS b
CROSS APPLY fnuserrank(b.userid)
where rank != 'TERM'
) bar
on foo.empid = bar.empid
and foo.monitordate = bar.maxdate
I usually prefer to use set based logic over aggregate functions, but whatever works. You can tweak it also by caching the results of your TVF join into a table variable.
EDIT:
http://www.sqlfiddle.com/#!3/613e4/17 - I mocked up your TVF here. Apparently sqlfiddle didn't like "go".
select foo.*, bar.*
from
(
SELECT f.*
FROM vwuser AS a
join fnuserrank f
on a.empid = f.empid
where rank != 'TERM'
) foo
left join
(
SELECT f1.empid [barempid], f1.monitordate [barmonitordate]
FROM vwuser AS b
join fnuserrank f1
on b.empid = f1.empid
where rank != 'TERM'
) bar
on foo.empId = bar.barempid
and foo.MonitorDate > bar.barmonitordate
where bar.barempid is null

Resources