PostgreSQL query issues - sql

I have a DB with multiple tables which also have multiple rows/columns with a layout similar to that shown below.
the site is in a table named sites and ID and Type are in a table labelled Site_EQ
Site ID Type
A0004 2 abc
A0004 3 abcd
A0004 4 abcde
A0005 2 abc
A0005 3 abcd
A0005 4 abcde
A0005 5 abc
A0005 6 abcd
A0005 7 abcde
Essentially what I am trying to do is filter the results by site finding the highest ID value per site and removing the others, so if for example A0010 had ID's 1-20 I would like the result to show.
A0010 20 Bla
and ignore the
A0010 1 Bla
A0010 2 Bla
and so on, but am not sure how to go about doing so as there is no set number of ID it could be 1-3 or 1-30, essentially giving me 30 results for a single site with only 1 column different (which I would like to filter to the highest value only).

Try:
select Site, ID, Type from
(select s.*, row_number() over (partition by Site order by ID desc) rn
from Site_EQ) q
where rn=1

This should do it:
SELECT T1.Site, T1.ID, T1.Type
FROM SomeTable T1, (SELECT Site, MAX(ID) AS ID
FROM SomeTable
GROUP BY Site) T2
WHERE T2.Site = T1.Site
AND T2.ID = T1.ID
The trick is have a sub query that gives you the Site + maximum ID, you can't retrieve the Type at the same time though due to the grouping so you need to join it again with the actual table.
Here you can find the explanation on Table Alias (T1 and T2):
http://www.postgresql.org/docs/9.1/static/queries-table-expressions.html#QUERIES-TABLE-ALIASES

Related

Oracle SQL - display values up to current record

Can I use LISTAGG or a similar analytical function in Oracle SQL to display all values in group up to current record?
This is my table:
id group_id value
-- -------- -----
1 1 A
2 1 B
3 1 C
4 2 X
5 2 Y
6 2 Z
I would like the following result:
id group_id values
-- -------- ------
1 1 A
2 1 AB
3 1 ABC
4 2 X
5 2 XY
6 2 XYZ
Here is one option, using a correlated subquery to handle the rollup of the value column:
SELECT
t1.id,
t1.group_id,
(SELECT LISTAGG(t2.val, '') WITHIN GROUP (ORDER BY t2.id)
FROM yourTable t2
WHERE t1.group_id = t2.group_id AND t2.id <= t1.id) AS vals
FROM yourTable t1
ORDER BY
t1.id;
Demo
The logic here is that, for each group, with rollup a concatenation of all values coming at or before the current id value in a given row.
Another approach to this, one which might perform and scale better, would be to use a recursive CTE. But, that would take more code, and might be harder to digest than what I wrote above.

How to select group of data and show one by one?

I have a table called leads and it has one column company. Each company puts up several rows (or leads) in this table. So the problem is that I use a simple SELECT * FROM Leads and display the output but some of the companies are pissed off that preference is given to one company over another but I cannot tell them it’s because they entered the lead first. So instead I’m looking for a solution where exactly 1 lead of each company is output and then when it exhausts showing 1 lead of each company the next set of 1-lead only appears.
So for example consider this as input table
Lead ID Company
1 ABC
2 ABC
3 ABC
4 BCD
5 CDE
6 EFG
7 EFG
8 CDE
9 ABC
10 BCD
11 ABC
Then I need something like
Lead ID Company
1 ABC
4 BCD
5 CDE
6 EFG
2 ABC
10 BCD
7 EFG
3 ABC
8 CDE
9 ABC
11 ABC
So here exactly 1 lead of each company appears and then the next company’s lead appears. When a particular companies leads are exhausted the remaining only appear. This is why in the last 2 results ABC appears twice as no other companies have unlisted leads.
This is probably the closest you can get:
select *
from Tab
order by
row_number() over (partition by Company order by LeadID)
The result will be ordered kind of randomly, you might add LeadID to the ORDER BY, see fiddle
;With Data As (
Select
*,
Rank() Over (Partition By Company Order By LeadID) Rnk
From LeadTableName
)
Select * From Data
Order By Rnk, Company

How do I get the latest record?

This is my table:
create table test (
id string,
name string,
age string,
modified string)
and this is my data:
id name age modifed
1 a 10 2011-11-11 11:11:11
1 a 11 2012-11-11 12:00:00
2 b 20 2012-12-10 10:11:12
2 b 20 2012-12-10 10:11:12
2 b 20 2012-12-12 10:11:12
2 b 20 2012-12-15 10:11:12
I want to get the latest record (include every columns id,name,age,modified) group by id,as the data above,the correct result is:
1 a 11 2012-11-11 12:00:00
2 b 20 2012-12-15 10:11:12
I am using below query in hive, it is working fine in sql http://sqlfiddle.com/#!2/bfbd5/42 but it is not working fine in hive
select * from test where (id, modified) in(select id, max(modified) from test group by id)
I am using 0.13 version of hive.
Hive only allows one column in an IN subquery. Try a left semijoin:
SELECT *
FROM test a
LEFT SEMI JOIN
(select id, max(modified) as modified from test) b
ON (a.modified = b.modified and a.id=b.id);
It sure seems like you could easily get he right answer using a straight forward query though. Select the max of the two columns and be sure to group by the columns that don't have aggregate functions.
select id
, name
, max(age) as age
, max(modified) as modified
from test
group by id, name;

SQL Server - How to display most recent records based on dates in two tables

I have 2 tables. I Want to list the records based on the recent date. For ex: from the following tables, I want to display ID 2 and ID 4 using a select statement. ID 2 and 4 are the most recent based on the dates from the second table. Please help me with the query. Thank you.
ID EXID PID REASON
1 1 1 XYZ
2 2 1 ABX
3 3 2 NNN
4 4 2 AAA
EXID EXDATE
1 1/1/2011
2 4/1/2011
3 3/1/2011
4 5/1/2011
Here you go, this ought to do it. Let me know if you have any questions.
SELECT
TBL.ID,
TBL.EXDATE
FROM
(
SELECT
T1.ID,
T2.EXDATE,
ROW_NUMBER() OVER(PARTITION BY T1.PID ORDER BY T2.EXDATE DESC) AS 'RN'
FROM
Table1 T1
INNER JOIN Table2 T2
ON T1.EXID = T2.EXID
) TBL
WHERE
TBL.RN = 1

SQL one to one without relation

Using Oracle 11
I'm wanting to pull data from a table, and add a column of calculated values which come from a subquery statement.
Example Table1 is:
COLUMN1: COLUMN2:
1 Group1
3 Group2
5 Group3
6 Group4
The subquery returns different values each time the query is run, but for the sake of this example let's say it returns thes values:
2
4
7
8
What I need is to combine the results
COLUMN1: COLUMN2: COLUMN3: (subquery - order does NOT matter)
1 Group1 2
3 Group2 4
5 Group3 7
6 Group4 8
But because the subquery is being calculated with each row return from the table, all I am getting is.
COLUMN1: COLUMN2: COLUMN3:
1 Group1 2
3 Group2 2
5 Group3 2
6 Group4 2
There is no way that I can think of to relate the table and the subquery, I've tried playing with ROWNUM but with no luck.
UPDATE
SELECT GD.*, N
FROM patrongroupsdesc GD,
(SELECT n
FROM patrongroupsdesc GD2,
(SELECT n, ROWNUM
FROM ( SELECT ROWNUM n
FROM DUAL
CONNECT BY LEVEL <= 100)
WHERE n >= 1) SUB
WHERE SUB.n = GD2.groupid(+) AND GD2.groupid IS NULL) SUB2
table PATRONGROUPSDESC is formatted as follows
groupid (NUMBER)
description (VARCHAR2)
...other data
SUB returns the values 1-100
SUB2 returns the gaps in groupid numbers
I'm essentially duplicating all data in this table except for one column
First you must know that if you don't have an ORDER BY clause then the order of the results comes with no guarantee at all.
Then, you can do:
WITH first_table AS (select *, ROWNUM AS rn FROM ...)
, secnd_table AS (select *, ROWNUM AS rn FROM ...)
SELECT first_table.*, secnd_table.*
FROM first_table INNER JOIN secnd_table USING (rn)
The trick here is that ROWNUM is assigned as a result comes out from a SELECT statement. Therefore if you want to paste tables like this, you must SELECT from your tables and store rownum in another column, and then from those two subselects you can join.