Using self joins sql query - db2

I have a Table, TEmployee where SequenceId, Date, EmplId, ExtnNumber, FName are the attributes, where SequenceId is unique and there will be multiple entries for same EmplId like
1 1/1/2014 55323 8793 Ryan
2 1/2/2014 83723 9898 Roy
3 1/1/2014 88838 8823 Mark
4 1/2/2014 83723 9832 Roy
5 1/3/2014 32323 2223 Tina
6 1/1/2014 55323 8744 Ryan
select * from TEmployee where EmplId in ('55323','83723') with urlists me the following..
1 1/1/2014 55323 8793 Ryan
2 1/2/2014 83723 9898 Roy
4 1/2/2014 83723 9832 Roy
6 1/1/2014 55323 8744 Ryan
But, i want to list the latest entry to be displayed.. by latest i mean SequenceId.. only entries 4 & 6..
Any pointers would be of good help. Thanks in Advance.

#Jimmy Smith beat me to it with a correct answer, but mine is a correlated subselect, so there is no need to repeat the EMPLID IN ('55323', '83723') part.
SELECT *
FROM TEMPLOYEE AS A
WHERE EMPLID IN ('55323', '83723')
AND SEQUENCEID = (
SELECT MAX(SEQUENCEID)
FROM TEMPLOYEE AS B
WHERE A.EMPLID = B.EMPLID
)
WITH UR

One method may be via a subquery,
select * from TEmployee where EmplId in ('55323', '83723') and SequenceId in (Select Max(SequenceId) where EmplId in ('55323', '83723'))

Related

fetch all records from table A and not empty from table B

I have 2 tables with following data
Table A
code Desc
1 john
2 dave
3 mike
4 lily
5 cobe
6 rose
Table B
code marks
1 30
2 35
3 40
5 29
RESULT TABLE
code Desc Marks
1 john 30
2 dave 35
3 mike 40
4 lily 0
5 cobe 29
6 rose 0
I have tried using left join but that displays only the records which are present in table B
LEFT JOIN should work. I think maybe you are trying to get the 0 values instead of the null-blanks? If so, you need to use COALESCE():
postgres=# select a.code,"Desc",coalesce("Marks",0) as "Marks"
from tablea a
left join tableb b on a.code=b.code;
code | Desc | Marks
------+------+-------
1 | john | 30
2 | dave | 35
3 | mike | 40
4 | lily | 0
5 | cobe | 29
6 | rose | 0
Disclosure: I work for EnterpriseDB (EDB)
A left join will work, but you must be using from students. The from table is the "left" side of the join. See
Visual Representation of SQL Joins
for an excellent visualization.
And use coalesce to turn the missing marks into 0.
select id, name, coalesce(mark, 0)
from students s
left join marks m on m.student_id = s.id
order by s.id;
Try it.

SQL Select based on each row of previous select

I have a table with answers regarding different questions, all of them numbered. There are basically these columns: IdAnswer (unique for each answer in the table), IdUser (which won't repeat even if the same user answer questions a second time), IdQuestion and Answer.
IdAnswer IdUser IdQuestion Answer
1 John 1 0
2 John 4 1
3 John 5 1
4 John 6 0
5 Bob 1 1
6 Bob 3 1
7 Bob 5 0
8 Mark 2 0
9 Mark 7 1
10 Mark 5 0
I'd like to select from this table all answers to a specific question (say, IdQuestion = 5), and also the last question each user answered just before question number 5.
In the end I need a table that should look like this:
IdAnswer IdUser IdQuestion Answer
2 John 4 1
3 John 5 1
6 Bob 3 1
7 Bob 5 0
9 Mark 7 1
10 Mark 5 0
I've managed to make this work using a cursor to iterate through each line from the first SELECT result (which filters by IdQuestion), but I'm not sure if this is the best (and fastest) way of doing it. Is there any more efficient way of achieving the same result?
And by the way, I'm using SQL Server Management Studio 2012.
Here is one way using LEAD function
select * from
(
select *,NextQ = Lead(IdQuestion)over(partition by IdUser order by IdAnswer)
from youtable
) a
Where 5 in (IdQuestion, NextQ )
for older versions
;WITH cte
AS (SELECT prev_id = Min(CASE WHEN IdQuestion = 5 THEN rn - 1 END) OVER( partition BY IdUser),*
FROM (SELECT rn = Row_number()OVER(partition BY IdUser ORDER BY IdAnswer),*
FROM Yourtable)a)
SELECT *
FROM cte
WHERE rn IN ( prev_id, prev_id + 1 )

Counting the size of a group in T-sql

I'd like to count the size of a group.
My table looks like that:
Name Number
Renee Scott 1
Bruno Cote 1
Andree Scott 2
Renee Scott 2
Pierre Dion 2
Pierre Dion 3
Louise Tremblay 3
Renee Scott 3
Andree Scott 3
Jean Barre 3
Bruno Cote 3
There are 2 Name associated with the Number 1, 3 Name with Number 2 and 6 Name with 3. I'd like to select this table where the Number is associated with 3 name or more.
Thank you.
SELECT * FROM TABLENAME WHERE NUMBER IN
(
SELECT NUMBER FROM TABLENAME GROUP BY NUMBER HAVING COUNT(*)>3
)

T-SQL How to get all items from a tree in T-SQL?

I have a problem with a t-sql query.
Let's say I have a categories tree (categories ID)
cat_table
1
|
2-\
| 3-\
6 | 5
| 4 |
... ...
ads_table
ad_ID
category_ID
of course the category_ID column references to the ID column in the cat_table
the problem is, how to get (recursive ?) all advertisements from all categories which the top-most parent is the 1st category?
try using a recursive Common Table Expressions, aka "CTE" (available in SQL Server 2005 and up) like this:
--go through a nested table supervisor - user table and display the chain
DECLARE #Contacts table (id varchar(6), first_name varchar(10), reports_to_id varchar(6))
INSERT #Contacts VALUES ('1','Jerome', NULL ) -- tree is as follows:
INSERT #Contacts VALUES ('2','Joe' ,'1') -- 1-Jerome
INSERT #Contacts VALUES ('3','Paul' ,'2') -- / \
INSERT #Contacts VALUES ('4','Jack' ,'3') -- 2-Joe 9-Bill
INSERT #Contacts VALUES ('5','Daniel','3') -- / \ \
INSERT #Contacts VALUES ('6','David' ,'2') -- 3-Paul 6-David 10-Sam
INSERT #Contacts VALUES ('7','Ian' ,'6') -- / \ / \
INSERT #Contacts VALUES ('8','Helen' ,'6') -- 4-Jack 5-Daniel 7-Ian 8-Helen
INSERT #Contacts VALUES ('9','Bill ' ,'1') --
INSERT #Contacts VALUES ('10','Sam' ,'9') --
DECLARE #Root_id char(4)
--get 2 and below
SET #Root_id=2
PRINT '#Root_id='+COALESCE(''''+#Root_id+'''','null')
;WITH StaffTree AS
(
SELECT
c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf
FROM #Contacts c
LEFT OUTER JOIN #Contacts cc ON c.reports_to_id=cc.id
WHERE c.id=#Root_id OR (#Root_id IS NULL AND c.reports_to_id IS NULL)
UNION ALL
SELECT
s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1
FROM StaffTree t
INNER JOIN #Contacts s ON t.id=s.reports_to_id
WHERE s.reports_to_id=#Root_id OR #Root_id IS NULL OR t.LevelOf>1
)
SELECT * FROM StaffTree
output:
#Root_id='2 '
id first_name reports_to_id Manager_id Manager_first_name LevelOf
------ ---------- ------------- ---------- ------------------ -----------
2 Joe 1 1 Jerome 1
3 Paul 2 2 Joe 2
6 David 2 2 Joe 2
7 Ian 6 6 David 3
8 Helen 6 6 David 3
4 Jack 3 3 Paul 3
5 Daniel 3 3 Paul 3
(7 row(s) affected)
change #Root_id to get different output:
#Root_id=null
id first_name reports_to_id Manager_id Manager_first_name LevelOf
------ ---------- ------------- ---------- ------------------ -----------
1 Jerome NULL NULL NULL 1
2 Joe 1 1 Jerome 2
9 Bill 1 1 Jerome 2
10 Sam 9 9 Bill 3
3 Paul 2 2 Joe 3
6 David 2 2 Joe 3
7 Ian 6 6 David 4
8 Helen 6 6 David 4
4 Jack 3 3 Paul 4
5 Daniel 3 3 Paul 4
(10 row(s) affected)
There is an option to avoid recurrency in tree browsing queries. You can add 'Path' column to your categories tree. It should contain each element ancestors IDs delimited with some non-numeric character (like slash).
For example your "ID=4" category's path would look like that: "/1/2/3/"
Now when you join your ads table to categories you need to do following:
select * from ads_table
inner join cat_table on cat_table.ID = ads_table.category_ID
where cat_table.Path like '/1/%'
And that's your query.
You can read more on this topic on my blog post
Are you familiar with Common Table Expressions in SQL Server? One of the many uses a CTE has is to do recursive queries.
The following is one of the best articles I've found on the subject:
https://web.archive.org/web/20210927200924/http://www.4guysfromrolla.com/webtech/071906-1.shtml

How can I select several rows with the Max column value which is grouped by another column?

I want to get the movie, character_name, and Visits of the 4 rows(*) having the max "Visits" value group by movie.
My table (D) is like this:
movie character_name Visits
1 Owen Lars 1
1 Obi-Wan Kanobi 2
1 Luke Skywalker 3*
2 Princess Leia 2
2 Luke Skywalker 3*
2 R2-D2 3*
3 Jabba the Hutt 1
3 Han Solo 2
3 Luke Skywalker 4*
The best coding I can think of is
select * FROM D
group by D.movie
HAVING max(Visits)
But i just can't get the right rows >
Can anyone tell me how I should revise it?
thanks so much!!
SELECT
D.*
FROM
D
INNER JOIN
(
SELECT
MOVIE
, MAX(VISITS) AS VISITS
FROM D
GROUP BY MOVIE) F ON D.MOVIE = F.MOVIE AND D.VISITS = F.VISITS