INNER JOIN with IN - sql

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;

Related

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;

Is it possible to do a nested left join within another left join?

So I want to do something like this:
SELECT ACC_NO
FROM
TABLENAME A
LEFT JOIN
(
TABLENAME B
LEFT JOIN TABLENAME C
ON B.FIELDNAME = C.FIELDNAME
) D
ON A.FIELDNAME = D.FIELDNAME
How would I achieve this?
Yes it is possible, Try like below
SELECT A.ACC_NO,A.FIELDNAME
FROM
TABLENAME A
LEFT JOIN
(
select B.* from TABLENAME B
LEFT JOIN TABLENAME C
ON B.FIELDNAME = C.FIELDNAME
) D
ON A.FIELDNAME = D.FIELDNAME
Yes, you can:
SELECT ACC_NO
FROM TABLENAME A LEFT JOIN
(TABLENAME B LEFT JOIN
TABLENAME C
ON B.FIELDNAME = C.FIELDNAME
) -- No alias is necessary
ON A.FIELDNAME = B.FIELDNAME;
However, this is unnecessary and verbose. Instead:
SELECT ACC_NO
FROM TABLENAME A LEFT JOIN
TABLENAME B
A.FIELDNAME = B.FIELDNAME LEFT JOIN
TABLENAME C
ON B.FIELDNAME = C.FIELDNAME;
I assume your query is actually more complex. This version is presumably equivalent to:
SELECT A.ACC_NO
FROM TABLENAME A
Unless you are interested in actually seeing duplicates that might be generated by the JOINs.

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

UNION ALL in CTE

I'm trying to get a UNION ALL working with a CTE which I'm using for paging. I need to get all records matching a set of criteria from two tables, then page the results. The first table's CTE looks like this:
;WITH Results_CTE AS (SELECT t1.SomeIntKey1, ROW_NUMBER() OVER (ORDER BY SomeIntKey1) AS RowNum
FROM Table1 t1
LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey1
WHERE Postcode LIKE 'CHX 1XX%'
) SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey1 = d.Key WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE)
The second table's paging SQL (which works fine) is:
;WITH Results_CTE AS (SELECT t2.SomeIntKey2, ROW_NUMBER() OVER (ORDER BY SomeIntKey2) AS RowNum
FROM Table2 t2
LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey2
WHERE Postcode LIKE 'CHX 1XX%'
) SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey2 = d.Key WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE)
For the combined paged data, I've tried something like:
;WITH Results_CTE AS (SELECT t2.SomeIntKey2, ROW_NUMBER() OVER (ORDER BY SomeIntKey2) AS RowNum
FROM Table2 t2
LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey2
WHERE Postcode LIKE 'CHX 1XX%'
UNION ALL
SELECT t1.SomeIntKey1
FROM Table1 t1
LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey1
WHERE Postcode LIKE 'CHX 1XX%'
) SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey2 = d.Key WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE)
However, this results in an error:
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
I know UNION ALLs can be confusing at the best of times, especially with joins, but I'm essentially getting a list of INT keys from two tables, then joining them to a third which contains the data I need (keys from both tables will be present in the joined column on the Data table.
You need to make sure that both result sets have the same columns:
WITH Results_CTE AS
(
SELECT
t2.SomeIntKey2 as Key,
ROW_NUMBER() OVER (ORDER BY SomeIntKey2) AS RowNum
FROM
Table2 t2
LEFT JOIN CalculatedData d
ON d.Key = t1.SomeIntKey2
WHERE Postcode LIKE 'CHX 1XX%'
UNION ALL
SELECT
t1.SomeIntKey1 as Key,
0 as RowNum
FROM
Table1 t1
LEFT JOIN CalculatedData d
ON d.Key = t1.SomeIntKey1
WHERE Postcode LIKE 'CHX 1XX%'
)
SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey2 = d.Key
WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE)
Please note that the second part of the UNION ALL now always returns 0 for the RowNum. If you want to have the RowNum column for the result of the UNION ALL you need another sub query:
WITH Results_CTE AS
(
SELECT
s.Key,
ROW_NUMBER() OVER (ORDER BY s.Key) AS RowNum
FROM
(
SELECT
t2.SomeIntKey2 as Key,
FROM
Table2 t2
LEFT JOIN CalculatedData d
ON d.Key = t1.SomeIntKey2
WHERE Postcode LIKE 'CHX 1XX%'
UNION ALL
SELECT
t1.SomeIntKey1 as Key
FROM
Table1 t1
LEFT JOIN CalculatedData d
ON d.Key = t1.SomeIntKey1
WHERE Postcode LIKE 'CHX 1XX%'
)
)
SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey2 = d.Key
WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE)
Your second SELECT in the your UNION ALL doesn't return the same number of columns, hence the problem.
Try:
;WITH Results_CTE AS (
SELECT IntKey, ROW_NUMBER() OVER (ORDER BY IntKey) AS RowNum
FROM
(
SELECT t2.SomeIntKey2 AS IntKey
FROM Table2 t2
LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey2
WHERE Postcode LIKE 'CHX 1XX%'
UNION ALL
SELECT t1.SomeIntKey1 AS IntKey
FROM Table1 t1
LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey1
WHERE Postcode LIKE 'CHX 1XX%'
) t
)
SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.IntKey = d.Key