How to find the max value without subquery - sql

To get the below result set I wrote following SQL:
SELECT t1.FilmName,
t2.CountryName,
t1.FilmRunTimeMinutes
FROM Film as t1
INNER JOIN country as t2 on t1.FilmCountryId = t2.CountryID
WHERE t1.FilmRunTimeMinutes = ( SELECT max(t2.FilmRunTimeMinutes)
FROM film as t2
WHERE t2.FilmCountryId = t1.FilmCountryId
)
ORDER BY FilmRunTimeMinutes DESC
I read this Link and tried the same method but I could not. So how can I get the same result set using by LEFT OUTER JOIN?
Film table has those columns:
FilmId --PK
FilmName
FilmCountryId --FK
FilmRunTimeMinutes
Country table has those columns:
CountryId --PK
CountryName
Thanks in advance.

use Row_Number window function
SELECT TOP 1 WITH ties t1.FilmName,
t2.CountryName,
t1.FilmRunTimeMinutes
FROM Film AS t1
INNER JOIN country AS t2
ON t1.FilmCountryId = t2.CountryID
ORDER BY Row_number() OVER(partition BY FilmCountryId ORDER BY FilmRunTimeMinutes DESC),
FilmRunTimeMinutes DESC;
or use CTE/Sub-Select
WITH cte
AS (SELECT t1.FilmName,
t2.CountryName,
t1.FilmRunTimeMinutes,
Rn = Row_number() OVER(partition BY FilmCountryId ORDER BY FilmRunTimeMinutes DESC)
FROM Film AS t1
INNER JOIN country AS t2
ON t1.FilmCountryId = t2.CountryID)
SELECT *
FROM cte
WHERE Rn = 1
ORDER BY FilmRunTimeMinutes DESC
if you really want left join approach then
SELECT t1.FilmName,
t2.CountryName,
t1.FilmRunTimeMinutes
FROM Film AS t1
INNER JOIN country AS t2
ON t1.FilmCountryId = t2.CountryID
LEFT JOIN Film AS t3
ON t3.FilmCountryId = t2.CountryID
AND t3.FilmRunTimeMinutes > t1.FilmRunTimeMinutes
WHERE t3.FilmID IS NULL
ORDER BY FilmRunTimeMinutes DESC

Try This
;WITH Q
AS
(
SELECT
RN = ROW_NUMBER() OVER(PARTITION BY t1.FilmCountryId ORDER BY t2.FilmRunTimeMinutes DESC),
t1.FilmName,
t2.CountryName,
t1.FilmRunTimeMinutes
FROM Film as t1
INNER JOIN country as t2 on t1.FilmCountryId=t2.CountryID
ORDER BY FilmRunTimeMinutes DESC
)
SELECT
*
FROM Q
WHERE RN = 1

Related

How to implement a LEFT OUTER JOIN CLAUSE after WITH AS?

Currently trying to figure out how to implement a SQL LEFT OUTER JOIN while using the SQL WITH AS clause. My code breaks down into 3 SELECT statements while using the same table, then using LEFT OUTER JOIN to merge another table on the id.
I need 3 SELECT statements before joining because I need a SELECT statement to grab the needed columns, ROW RANK the time, and set WHERE clause for the ROW RANK.
SELECT *
(
WITH employee AS
(
SELECT id, name, department, code, time, reporttime, scheduled_time
FROM table1 AS a
WHERE department = "END"
),
employe_v2 as
(
SELECT address
,ROW_NUMBER() OVER (PARTITION BY id ORDER BY time desc, reporttime desc, scheduled_time desc) AS row_rank
FROM table1 AS b
)
SELECT *
FROM employee, employee_v2
WHERE row_rank = 1
) t1
LEFT OUTER JOIN
(
SELECT b.id, b.new_code, b.date
FROM table2 AS b
WHERE b.newcode != "A"
) t2
ON t1.id = t2.id
Group BY t1.id, t1.name, t1.department, t1.code, t1.time, t1.reporttime,
t1.scheduled_time, t1.row_rank, t2.id, t2.new_code, t2.date
How I could fix my code?
not sure if group by is needed, i see no aggregation whatsover
but if it's something you need , you can add at the end of final select and ofcourse you have to take care of columns/aggregation in select
nevertheless you can simplify your query as below :
with employee as (
select * from (
select id, name, department, code, time, reporttime, scheduled_time, address
,row_number() over (partition by id order by time desc, reporttime desc, scheduled_time desc) AS row_rank
from table1
) t where row_rank =1
)
select t1.*, b.id, b.new_code, b.date
from employee t1
left join table2 as t2
on t1.id = t2.id
where t2.newcode != "A"

Oracle-Join with same table multiple times with different where condition

Here is my case,
SELECT
A.TAB1_COL1,B.TAB2_COL4,C.TAB2_COL4
FROM TABLE1 A,
LEFT OUTER JOIN
(SELECT * FROM
(SELECT TAB2_COL1, TAB2_COL2, TAB2_COL4, ROW_NUMBER() OVER (PARTITION BY TAB2_COL1,TAB2_COL2 ORDER BY TAB2_COL3 DESC ) AS ROW_NUM
FROM TABLE2
WHERE TAB2_COL2=2
) WHERE ROW_NUM=1
) B ON A.TAB1_COL1=B.TAB2_COL1
LEFT OUTER JOIN
(SELECT * FROM
(SELECT TAB2_COL1, TAB2_COL2, TAB2_COL4, ROW_NUMBER() OVER (PARTITION BY TAB2_COL1,TAB2_COL2 ORDER BY TAB2_COL3 DESC ) AS ROW_NUM
FROM TABLE2 WHERE TAB2_COL2=5
) WHERE ROW_NUM=1
) C ON A.TAB1_COL1=C.TAB2_COL1 AND A.TAB1_COL2=C.TAB2.COL5
LEFT OUTER JOIN
(SELECT * FROM
(SELECT TAB2_COL1, TAB2_COL2, TAB2_COL4, ROW_NUMBER() OVER (PARTITION BY TAB2_COL1,TAB2_COL2 ORDER BY TAB2_COL3 DESC ) AS ROW_NUM
FROM TABLE2 WHERE TAB2_COL2=8
) WHERE ROW_NUM=1
) D ON A.TAB1_COL1=D.TAB2_COL1
This code will work.But, I'm left joining with same table multiple times. In my case, it was around 25 times. Reference table has around 200 million records. Partition to remove dups is taking much time.
Any other effective way of writing to make it process faster. Kindly help.
Thanks
If I understand correctly, you can use conditional aggregation:
select t1.tab1_col1,
max(case when tab2_col2 = 2 then tab2_col4 end),
max(case when tab2_col2 = 5 then tab2_col4 end),
max(case when tab2_col2 = 8 then tab2_col4 end)
from table1 t1 left join
(select t2.*,
row_number() over (partition by tab2_col1, tab2_col2 order by tab2_col3 desc) as seqnum
from table2 t2
) t2
on t1.tab1_col1 = t2.tab2_col1
group by t1.tab1_col1;

Latest record and sum SQL

I'm looking for solution for this problem.
Table:
i want this output (show latest tier based on maximum transaction id)
You can do :
select *, sum(select sum(t1.poin)
from table t1
where t1.member_id = t.member_id
) as poin,
sum(select sum(t1.freq)
from table t1
where t1.member_id = t.member_id
) as freq
from table t
where trans_id = (select t1.trans_id
from table t1
where t1.member_id = t.member_id
order by t1.trans_id desc
fetch first 1 rows only
);
Most DBMS has support fetch first 1 rows only method.
If, you are working with SQL Server, then you can directly express it as :
select t.member_id, tt.*
from (select *, row_number() over (partition by member_id order by trans_id desc) as seq
from table
) t cross apply (
select sum(t1.poin) as poin, sum(t1.freq) as freq
from table t1
where t1.member_id = t.member_id
) tt
where t.seq = 1;

Joining two queries that have INNER JOINS in them

I'm trying to join these two SQL queries together. My data is at https://policevideorequests.cartodb.com/tables/seattle_police_govqa_audit_trails which has a Postgresql SQL API.
SELECT
t1.customer_id, t1.c,
t2.customer_name, t2.customer_email, t2.customer_email_domain
FROM
(SELECT
a.customer_id, count(a.customer_id) as c
FROM
(SELECT customer_id, reference_no
FROM seattle_police_govqa_audit_trails
WHERE customer_id NOT IN (5, 0, -1)
GROUP BY customer_id, reference_no) a
GROUP BY
a.customer_id
ORDER BY
count(a.customer_id) DESC) t1
INNER JOIN
(SELECT DISTINCT
customer_id,
INITCAP(LOWER(SUBSTRING(new_value FROM 'Dear (.*?):</div>'))) as customer_name,
LOWER(SUBSTRING(new_value FROM 'login:<b>(.*?)</b>')) as customer_email,
LOWER(SUBSTRING(new_value FROM 'login:<b>.*?#(.*?)</b>')) as customer_email_domain
FROM
seattle_police_govqa_audit_trails
WHERE
SUBSTRING(new_value FROM 'Dear (.*?):</div>') IS NOT NULL) t2 ON t1.customer_id = t2.customer_id
ORDER BY
t1.c DESC
SELECT DISTINCT
t1.new_value as requester_type, t2.customer_id
FROM
(SELECT
reference_no, new_value
FROM
seattle_police_govqa_audit_trails
WHERE
action_desc = 154) t1
INNER JOIN
(SELECT
reference_no, customer_id
FROM
seattle_police_govqa_audit_trails
WHERE
customer_id NOT IN (0, -1, 5)) t2 ON t1.reference_no = t2.reference_no
My attempt at joining the two:
SELECT t1.customer_id,t3.requester_typer,t1.c,t2.customer_name,t2.customer_email,t2.customer_email_domain,t2.customer_email_domain_tld FROM (SELECT a.customer_id,count(a.customer_id) as c FROM (SELECT customer_id, reference_no FROM seattle_police_govqa_audit_trails WHERE customer_id NOT IN (5,0,-1) GROUP BY customer_id,reference_no) a GROUP BY a.customer_id ORDER BY count(a.customer_id) DESC) t1
INNER JOIN (SELECT DISTINCT customer_id,INITCAP(LOWER(SUBSTRING(new_value FROM 'Dear (.*?):</div>'))) as customer_name,LOWER(SUBSTRING(new_value FROM 'login:<b>(.*?)</b>')) as customer_email, LOWER(SUBSTRING(new_value FROM 'login:<b>.*?#(.*?)</b>')) as customer_email_domain, LOWER(SUBSTRING(new_value FROM 'login:<b>.*?#.*?\.(.*?)</b>')) as customer_email_domain_tld FROM seattle_police_govqa_audit_trails WHERE SUBSTRING(new_value FROM 'Dear (.*?):</div>') IS NOT NULL) t2
ON t1.customer_id = t2.customer_id ORDER BY t1.c DESC
INNER JOIN (SELECT DISTINCT t1.new_value as requester_type,t2.customer_id FROM (SELECT reference_no,new_value FROM seattle_police_govqa_audit_trails WHERE action_desc = 154) t1
INNER JOIN (SELECT reference_no,customer_id FROM seattle_police_govqa_audit_trails WHERE customer_id NOT IN (0,-1,5)) t2
ON t1.reference_no = t2.reference_no) as t3
ON t2.customer_id = t3.customer_id
I get the error "syntax error near INNER"
The problem in your SQL query is that you tried to keep ORDER BY in the middle. The ORDER BY clause must be moved all the way to the back of the query, because ordering is applied to the entire query, not to its parts.
Try this:
SELECT t1.customer_id,t3.requester_typer,t1.c,t2.customer_name,t2.customer_email,t2.customer_email_domain,t2.customer_email_domain_tld FROM (SELECT a.customer_id,count(a.customer_id) as c FROM (SELECT customer_id, reference_no FROM seattle_police_govqa_audit_trails WHERE customer_id NOT IN (5,0,-1) GROUP BY customer_id,reference_no) a GROUP BY a.customer_id ORDER BY count(a.customer_id) DESC) t1
INNER JOIN (SELECT DISTINCT customer_id,INITCAP(LOWER(SUBSTRING(new_value FROM 'Dear (.*?):</div>'))) as customer_name,LOWER(SUBSTRING(new_value FROM 'login:<b>(.*?)</b>')) as customer_email, LOWER(SUBSTRING(new_value FROM 'login:<b>.*?#(.*?)</b>')) as customer_email_domain, LOWER(SUBSTRING(new_value FROM 'login:<b>.*?#.*?\.(.*?)</b>')) as customer_email_domain_tld FROM seattle_police_govqa_audit_trails WHERE SUBSTRING(new_value FROM 'Dear (.*?):</div>') IS NOT NULL) t2
ON t1.customer_id = t2.customer_id
INNER JOIN (SELECT DISTINCT t1.new_value as requester_type,t2.customer_id FROM (SELECT reference_no,new_value FROM seattle_police_govqa_audit_trails WHERE action_desc = 154) t1
INNER JOIN (SELECT reference_no,customer_id FROM seattle_police_govqa_audit_trails WHERE customer_id NOT IN (0,-1,5)) t2
ON t1.reference_no = t2.reference_no) as t3
ON t2.customer_id = t3.customer_id
ORDER BY t1.c DESC

Add row number to this T-SQL query

How can I add ROW numbers to this query result?
SELECT DISTINCT
VehicleSpecs.SubmittedById,
COUNT(VehicleSpecs.SubmittedById) AS NumCars,
aspnet_Users.UserName
FROM
VehicleSpecs
INNER JOIN aspnet_Users ON VehicleSpecs.SubmittedById = aspnet_Users.UserId
WHERE
(LEN(VehicleSpecs.SubmittedById) > 0)
GROUP BY
VehicleSpecs.SubmittedById,
aspnet_Users.UserName
ORDER BY
NumCars DESC
Add: ROW_NUMBER() OVER (ORDER BY NumCars)
EDIT:
WITH t1 AS
( SELECT DISTINCT
VehicleSpecs.SubmittedById ,
COUNT(VehicleSpecs.SubmittedById) AS NumCars ,
aspnet_Users.UserName
FROM VehicleSpecs
INNER JOIN aspnet_Users ON VehicleSpecs.SubmittedById = aspnet_Users.UserId
WHERE ( LEN(VehicleSpecs.SubmittedById) > 0 )
GROUP BY VehicleSpecs.SubmittedById ,
aspnet_Users.UserName
)
SELECT ROW_NUMBER() OVER ( ORDER BY NumCars ), *
FROM t1
ORDER BY NumCars
Wrap you entire query in a sub query and add row_number in the outer query.
select *, row_number() over(order by (select 0)) as rn
from
(
select distinct -- your columns
from YourTable
) as T
order by NumCars desc