Syntax Error on Distinct inside a Join in SQL Server - sql

I have a query and I need to display distinct values from a join. I have this kind of SQL query
select
a.member_id, b.registered_time
from
b
left join
(select distinct a.member_id from a) on b.mirror_id = a.mirror_id
order by
b.registered_time desc;
But this query returns me a syntax error
Incorrect syntax near the keyword 'on'
How can I fix that?
I also tried doing this query but it returns an error
Invalid column name 'mirror_id'
Code:
select
a.member_id, b.registered_time
from
b
left join
(select distinct a.member_id from a) a on b.mirror_id = a.mirror_id
order by
b.registered_time desc;
I also tried doing this kind
select
a.member_id, b.registered_time
from
b
left join
(select distinct a.member_id from a) AP on b.mirror_id = a.mirror_id
order by
b.registered_time desc;
but it returns an error that multipart identifier couldn't be bound
I have these kind of result from my join:
For example I have these two tables
Table a
Table 2
But I need to display only one member_id with the latest registered_time

Original (reformatted):
select a.member_id, b.registered_time
from b
left join (select distinct a.member_id from a)
on b.mirror_id = a.mirror_id
order by b.registered_time desc;
Step 1, place the alias AFTER the subquery:
select a.member_id, b.registered_time
from b
left join (select distinct a.member_id from a) a
------------------------------------------------^
on b.mirror_id = a.mirror_id
order by b.registered_time desc;
Step 2, INCLUDE the column mirror_id inside the subquery
select a.member_id, b.registered_time
from b
left join (select distinct a.member_id, mirror_id from a) a
---------------------------------------^^^^^^^^^^^
on b.mirror_id = a.mirror_id
order by b.registered_time desc;
At this point the query should work, but I cannot tell if it is functionally what you want unless you provide sample data and expected result.
EDIT (2)
a simple GROUP BY may be used to arrive at a max date per member:
SELECT
a.member_id
, max(b.registered_time) registered_time
FROM a
INNER JOIN b ON a.mirror_id = b.mirror_id
GROUP BY
a.member_id
If you need whole rows from table a, then the row_number() approach is better:
SELECT d.*
FROM (
SELECT
a.*
, b.registered_time
, row_number() over(partition by a.member_id order by b.registered_time DESC) rn
FROM a
INNER JOIN b ON a.mirror_id = b.mirror_id
) d
WHERE d.rn = 1

You need a table alias:
select a.member_id, b.registered_time
from b left join
(select distinct a.member_id
from a
) a
-------^
on b.mirror_id = a.mirror_id
order by b.registered_time desc;
EDIT:
Well, you need the mirror_id to do the join. Why do you need the distinct? In any case, you can try:
select a.member_id, b.registered_time
from b left join
(select a.mirror_id, min(a.member_id) as member_id
from a
group by a.mirror_id
) a
on b.mirror_id = a.mirror_id
order by b.registered_time desc;

Related

INNER JOIN with IN

I want to combinate the following function with a table for many numbers(here "400") in an other table in Access with the join function.
SELECT tblData.ID,tblData.Data,(
SELECT TOP 1 d.Data
FROM tblData d
WHERE d.Data **< 400**
AND d.ID <= tblData.ID
ORDER BY d.ID DESC
) AS X
FROM tblData;
The join function is for arrays.
But you can join two tables, perhaps like this:
SELECT tblData.ID,tblData.Data,(
SELECT TOP 1 d.Data
FROM tblData d
INNER JOIN OtherTable
ON d.Data = OtherTable.Data
WHERE d.ID <= tblData.ID
ORDER BY d.ID DESC
) AS X
FROM tblData;

Removing duplicate values from a column in SQL

I have two tables A (group_id, id, subject) and B (id, date). Below is the joint table of tables A and B on id. I have tried using distinct and partition to remove the duplicates in group_id(field) only, but no luck:
My code:
select
a.group_id, a.id, a.subject, b.date
from
A a
inner join
(select
b.*,
row_number() over (partition by group_id order by date asc) as seqnum
from
B b) b on a.id = b.id and seqnum = 1
order by
date desc;
I got this error when I ran the code:
Partitioning can not be used stand-alone in query near 'partition by group_id order by date asc) as seqnum from B' at line 1
This is my expected result:
Thank you in advance!
It looks like you want the earliest date for each row in the table you show. Your question mentions two tables, but you only show one.
I recommend a correlated subquery in most databases:
select b.*
from b
where b.date = (select min(b2.date)
from b b2
where b2.group_id = b.group_id
);
I see. You need to join first and then use row_number():
select ab.*
from (select a.group_id, a.id, a.subject, b.date,
row_number() over (partition by a.group_id order by b.date) as seqnum
from A a join
B b
on a.id = b.id
) ab
where seqnum = 1
order by date desc;
You are almost there. But the column that you try to use to partition (ie group_id) comes from table a, which is not available in the subquery.
You would need to JOIN and assign the row number in a subquery, and then filter in the outer query.
select *
from (
select
a.group_id,
a.id,
a.subject,
b.date,
row_number() over (partition by a.group_id order by b.date asc) as seqnum
from a
inner join b on ON a.id = b.id
)
where seqnum = 1
ORDER BY date desc;
Another way to achieve your goal though it may not be the efficient one
SELECT
A.group_id, A.id, B.Date, A.subject
FROM A
INNER JOIN B
ON A.Id = B.Id
INNER JOIN
(
SELECT
A.Group_id, MIN(B.Date) AS Date
FROM A
INNER JOIN B
ON A.Id = B.Id
GROUP BY A.group_id
) AS supportTable
ON A.group_id = supportTable.group_id
AND B.Date = supportTable.Date

Max(date) in inner query

I was given sample SQL which does not seem to do what I need.
Big table has 4 million rows and small table has 600 thousand rows.
/* Sample code: (I was given this sample by a senior analyst) */
SELECT SUM(BigTable.VALUE)
FROM BigTable INNER JOIN SmallTable
WHERE BigTable.ID = SmallTable.ID
AND BigTable.VALUATION_DATE IN
(SELECT MAX(VALUATION_DATE)
FROM BigTable)
GROUP BY BigTable.ID
/* My code: (I placed a WHERE in the inner query) */
SELECT BigTable.ID, SUM(BigTable.VALUE)
FROM BigTable INNER JOIN SmallTable
WHERE BigTable.ID = SmallTable.ID
AND BigTable.VALUATION_DATE IN
(SELECT MAX(VALUATION_DATE)
FROM BigTable INNER JOIN SmallTable
WHERE BigTable.ID = SmallTable.ID)
GROUP BY BigTable.ID
If ID xyz has three accounts with values $1, $2, $3 respectively on the most recent date, I want to return the sum of all accounts on that date: xyz, $6
So the INNER JOIN syntax you are using I believe is incorrect. After the INNER JOIN table that will be joined, you need to state ON what columns you wish to join the tables on.
The following query is the correct syntax (although it may not be correct for your implementation).
SELECT BigTable.ID, SUM(BigTable.VALUE)
FROM BigTable INNER JOIN SmallTable
ON BigTable.ID = SmallTable.ID
WHERE BigTable.VALUATION_DATE IN
(SELECT MAX(VALUATION_DATE)
FROM BigTable INNER JOIN SmallTable
ON BigTable.ID = SmallTable.ID)
GROUP BY BigTable.ID
Only when you are doing cross joins, and natural joins do you not use the ON keyword and only use the WHERE command.
You should avoid the where clause and use the ON Clause
SELECT SUM(BigTable.VALUE)
FROM BigTable
INNER JOIN SmallTable ON BigTable.ID = SmallTable.ID
AND BigTable.VALUATION_DATE = (
SELECT MAX(VALUATION_DATE)
FROM BigTable)
and youn should not use a group by id ..
Use window functions:
SELECT b.ID, b.VALUE
FROM (SELECT b.*,
ROW_NUMBER() OVER (PARTITION BY b.id ORDER BY b.VALUATION_DATE DESC) as seqnum
FROM BigTable b
) b JOIN
SmallTable s
ON b.ID = s.ID
WHERE b.seqnum = 1;
I don't think aggregation is necessary. But, if you have multiple values on the same date for the same id, then:
SELECT b.ID, SUM(b.VALUE)
FROM (SELECT b.*,
RANK() OVER (PARTITION BY b.id ORDER BY b.VALUATION_DATE DESC) as seqnum
FROM BigTable b
) b JOIN
SmallTable s
ON b.ID = s.ID
WHERE b.seqnum = 1
GROUP BY b.id;

SQL: Modifying Inner Join to Select One Row

I have two tables, A and B that I want to inner join on location. However, for each row in A, there are many rows in B whose location matches. I want to end up with at most the same number of rows as in A. Specifically, I want to take the row in B where date is earliest. Here's what I have so far:
SELECT *
FROM A
INNER JOIN B ON A.location = B.location
How would I modify this so that each row in A only gets joined with a single row in B (using the earliest date)?
Attempt:
SELECT *
FROM A
INNER JOIN B ON A.location = B.location
AND B.date = (SELECT MIN(date) FROM B)
Is that the right approach?
You can use the ANSI/ISO standard row_number() function:
SELECT *
FROM A INNER JOIN
(SELECT B.*, ROW_NUMBER() OVER (PARTITION BY B.location ORDER BY B.date) as seqnum
FROM B
) B
ON A.location = B.location AND seqnum = 1;
SELECT TOP(1) * FROM A
INNER JOIN B ON
A.LOCATION=B.LOCATION
ORDER BY B.DATE

Select group with maximum value of aggregate function

I have this query
select dca_sif, maxupp
from (select d.sifra dca_sif , sum(col1) as maxup
from tableD d join tablev v on d.id=v.d_id
join tableT t on v.id=t.v_id
group by d.sif
order by maxup desc
)
where rownum=1;
This returns first value, but If I have more groups with same maxup, how can I return all of them?
If I delete rownum=1, it returns all groups and coresponding maxup.
I want to return max(sum(col1)) but this cause error. Database is oracle.
You can try somthing like this:-
SELECT dca_sif, MAX(maxup)
FROM (SELECT d.sifra dca_sif , SUM(col1) AS maxup
FROM tableD d JOIN tablev v ON d.id=v.d_id
JOIN tableT t ON v.id=t.v_id
GROUP BY d.sif
ORDER BY maxup DESC
)
WHERE ROWNUM=1
GROUP BY dca_sif;
This might be helpful to you.
You can combine your select with the same select, but without the rownum limitation. Than join on the max id. There are many tables in your statement, so it is difficult to test for me, but this should work:
SELECT count(qry2.dcasif) || ' groups', sum( qry2.maxup2)
FROM ( SELECT dca_sif, MAX (maxup) AS maxup1
FROM ( SELECT d.sifra dca_sif, SUM (col1) AS maxup
FROM tabled d
JOIN tablev v ON d.id = v.d_id
JOIN tablet t ON v.id = t.v_id
GROUP BY d.sif
ORDER BY maxup DESC)
WHERE ROWNUM = 1
GROUP BY dca_sif) qry1
, ( SELECT dca_sif, MAX (maxup) AS maxup2
FROM ( SELECT d.sifra dca_sif, SUM (col1) AS maxup
FROM tabled d
JOIN tablev v ON d.id = v.d_id
JOIN tablet t ON v.id = t.v_id
GROUP BY d.sif
ORDER BY maxup DESC)
GROUP BY dca_sif) qry2
WHERE qry1.maxup1 = qry2.maxup2
SELECT dca_sif, maxup
FROM
(SELECT a.*,rank() over(order by maxup desc)as Rank
FROM (SELECT d.sifra dca_sif , SUM(col1) AS maxup
FROM tableD d JOIN tablev v ON d.id=v.d_id
JOIN tableT t ON v.id=t.v_id
GROUP BY d.sif
)a)
WHERE Rank=1