Get Last Row or Smallest data then join two tables - sql

Using this Question where it is related Get Last Row of Different id then display data that is greater than zero
I would like to join another table
This is my table2
+----+--------+
| id | name |
+----+--------+
| 1 | Taylor |
| 2 | Zac |
| 3 | Scott |
| 4 | Emma |
+----+--------+
If I use this code...
SELECT DISTINCT t1.id, t1.amount, t2.name FROM table1 t1, table2 t2 WHERE t1.amount = (SELECT MIN(t1.amount) FROM table1 WHERE id= t1.id) AND t1.[t1.amount]>0 AND t1.[id]=t2.[id];
... then these result show...
+----+--------+-------+
| id | amount | name |
+----+--------+-------+
| 2 | 100 | Zac |
+----+--------+-------+
only 1 data is showing
what i want is both data in the table
+----+--------+-------+
| id | amount | name |
+----+--------+-------+
| 2 | 100 | Zac |
| 4 | 200 | Emma |
+----+--------+-------+

SELECT DISTINCT t.id,t2.name,t.amount
FROM table t
INNER JOIN table2 t2 ON t.id=t2.id
WHERE amount = (SELECT MIN(amount) FROM table WHERE id= t.id)
and amount>0;

Believe you're looking for a subquery of the first table, try the following:
SELECT DISTINCT t1.id, t1.amount, t2.name
FROM (SELECT DISTINCT id, amount FROM table t
WHERE amount = (SELECT MIN(amount) FROM table WHERE id= t.id)
and amount>0) t1, table2 t2
WHERE t1.[id]=t2.[id];
Not sure why your current query isn't working but hope this helps!

Please try the following...
SELECT table2.id AS id,
minAmount AS amount,
name
FROM ( SELECT id,
MIN( amount ) AS minAmount
FROM table1
GROUP BY id
HAVING MIN( amount ) > 0
) AS table1Refiner
INNER JOIN table2 ON table1Refiner.id = table2.id;
This statement works by obtaining the results as per your first Question and joining them to table2 based on their shared values of id, effectively appending the corresponding name to each id and amount. The fields are then selected and output.
If you have any questions or comments, then please feel free to post a Comment accordingly.

Related

Repeat same data based on for each value in another table's column

I have two data tables:
+---------+--------+ +---------+
|Account | Value | | Version |
+---------+--------+ +---------+
| 1 | 10 | | a |
+---------+--------+ +---------+
| 2 | 20 | | b |
+---------+--------+ +---------+
Basically, what I want to do is to add column "version" to the first table and repeat data for each version, e.g:
+---------+--------+---------+
|Account | Value | Version |
+---------+--------+---------+
| 1 | 10 | a |
+---------+--------+---------+
| 2 | 20 | a |
+---------+--------+---------+
| 1 | 10 | b |
+---------+--------+---------+
| 2 | 20 | b |
+---------+--------+---------+
Unfortunately, I can't hard-write the version names since they change very frequently, but data itself is static. Any idea how to do it with SQL?
This sounds like a cross join:
select t1.*, t2.*
from table1 t1 cross join
table2 t2;
This produces a Cartesian product of the two tables -- which is exactly what your question describes.
Note that if either table is empty, this will return no rows.
You can do this in two ways:
First: by executing the below script you will have a table that you desired.
create table yourTableName as
(select t1.*, t2.*
from table1 t1 cross join
table2 t2
)
Second:
Add column version to table1 as nullable
alter table table1 add column version varchar(20)
insert combination data to table1
insert into table1 (Account, Value, Version)
(select t1.*, t2.*
from table1 t1 cross join
table2 t2
)
delete rows that version column is null
delete from table table1 where version is null

find records having more than one distinct colum value

Given table t1 with columns Id ( text, primary key ) and place (text) like below.
+-------+-----------+
| Id | place |
+-------+-----------+
| abcde | Santori |
| bcdef | Krypt |
| cdefg | Bali |
| defgh | Bangkok |
| abcde | Colombo |
+-------+-----------+
I need to find out the records for Ids having more than one distinct place. In the above example the output shall be
+-------+-----------+
| Id | place |
+-------+-----------+
| abcde | Santori |
| abcde | Colombo |
+-------+-----------+
I would use exists :
select t.*
from table t
where exists (select 1 from table t1 where t1.id = t.id and t1.place <> t.place);
I think it is OK for you:
SELECT ID, PLACE FROM T1 as A
WHERE A.ID IN
(SELECT ID FROM T1 AS B
GROUP BY ID
HAVING count(*) > 1
)
In a subquery, you need to get count of distinct place and get the ID. And then use an outer query to fetch all records.
Fiddle Example
select * From T1
where T1.ID in
(select ID from T1
group by ID
having count(distinct PLACE) > 1
)

SQL Join to the latest record

I want to join tables in such a way that it fetches only latest record from one of the tables:
The following are my data
Table_One:
+----+------+
| ID | Name |
+----+------+
| 1 | John |
| 2 | Tom |
| 3 | Anna |
+----+------+
Table_two:
+----+----------+-----------+
| ID | Visit ID | Date |
+----+----------+-----------+
| 1 | 2513 | 5/5/2001 |
| 1 | 84654 | 10/5/2012 |
| 1 | 454 | 4/20/2018 |
| 2 | 754 | 4/5/1999 |
| 2 | 654 | 8/8/2010 |
| 2 | 624 | 4/9/1982 |
| 3 | 7546 | 7/3/1997 |
| 3 | 246574 | 6/4/2015 |
| 3 | 15487 | 3/4/2017 |
+----+----------+-----------+
Results needed after Join:
+----+------+----------+-----------+
| ID | Name | Visit ID | Date |
+----+------+----------+-----------+
| 1 | John | 454 | 4/20/2018 |
| 2 | Tom | 654 | 8/8/2010 |
| 3 | Anna | 246574 | 6/4/2015 |
+----+------+----------+-----------+
Different database engines have varying ways to get the top row from table 2 per group (you can google for "SQL windowing functions" and your product). Since you don't state what engine you're using it's impossible to give the most appropriate or most performant solution.
The following method should work in most or all SQL engines but will not be especially performant over a large data set (it will benefit from a composite index Table2(ID, Date)). The details of how you specify the aliases for the tables may differ a bit among engines but you can use this as a guide. A windowing function solution will probably be more efficient.
SELECT ID, Name, VisitID, Date FROM Table1 T1 INNER JOIN Table2 T2 +
ON T1.ID = T2.ID
WHERE NOT EXISTS (SELECT * FROM Table2 T2B WHERE T2B.ID = T1.ID AND T2B.Date > T2.Date)
I suspect you have SQL Server if so, then you can use APPLY:
select o.*, tt.*
from Table_One o
cross apply ( select top 1 t.VisitDate, t.Date
from table_two t
where t.id = o.id
order by t.date desc
) tt;
You can filter out "latest visit" using
SELECT ID,MAX(DATE) FROM TABLE_TWO GROUP BY ID;
You then join that to TABLE_ONE (... ON .ID = .ID) to pick up the Name column and then join that again to TABLE_TWO (... ON ID=ID AND DATE=DATE) if you need to pick up the VISIT_ID as well.
Specific DBMS's might have proprietary/idiosyncratic extensions typically serving the purpose of allowing the optimizer do a better job (e.g. allowing the optimizer to understand that the "joining back to TABLE_TWO can be eliminated). Thinking here of SELECT TOP 1 ... and the like.
SELECT ID,Name,Visit_ID,Date
FROM
(SELECT *, ROW_NUMBER() OVER(PARTITION BY ID Date DESC) as seq
FROM Table2 LEFT OUTER JOIN
Table1 ON Table2.ID = Table1.ID) as mainTable
WHERE seq = 1
I'm not a 100% sure if this is correct since the Visit ID might just throw every record right back at you. However you can find some great documentation here: https://www.w3resource.com/sql/aggregate-functions/max-date.php
select t1.ID,t1.Name,t2.visit_ID, Max(t2.Date) from Table_Two t2
inner join Table_One t1
on(t2.ID=t1.ID)
group by t1.ID,t1.Name,t2.visit_ID
something like this should work though, i think that this is also the same as #Erwin Smout proposes
select a.ID, t1.Name, a.date,t2.Visit_ID (
select ID, max(date)'date' from Table_Two
group by ID) a
inner join Table_One t1
on( a.ID=t1.ID)
inner join Table_Two t2
on(a.ID=t2.ID and a.Date=t2.Date)
This is the answer to your question
SELECT t1.ID, t1.Name, t2.visit_id, t2.Date FROM table1 t1 INNER JOIN table2 t2 ON t1.ID = t2.ID WHERE NOT EXISTS (SELECT * FROM table2 t2b WHERE t2b.ID = t1.ID AND t2b.Date > t2.Date)

SQL get data that doesn't exist on another table

I'm trying to get a query that get me a data that exist in table1 but not on table2, but has the same id with data table2.
In the following example, I'm trying to get 'SecID-by_Bank' 12456 which shares the same ISIN as another 2 items in table2.
I've tried the following query, but it returned me every data that's not on table2, not just the one that shares the same ISIN.
Query:
SELECT tb1_isin, tb1_SecID_by_Bank
FROM table1
WHERE not EXISTS (
SELECT top 1 null
FROM table2
WHERE table1.tb1_ISIN = table2.tb2_isin
)
Table 1
--------------------------------------------
Row | SecID_by_Bank | Desc | ISIN
--------------------------------------------
1 | 421345 | BlaBla | US1354
--------------------------------------------
499 | 34345 | 2.US | XS1545
--------------------------------------------
500 | 45676 | 2/US | XS1545
--------------------------------------------
501 | 12456 | 2-US | XS1545
--------------------------------------------
Table 2
--------------------------------------------
Row | SecID_by_Bank | Desc | ISIN
--------------------------------------------
1 | 34345 | 2.US | XS1545
--------------------------------------------
2 | 45676 | 2/US | XS1545
Query result needed:
SecID_by_Bank | Desc | ISIN
-------------------------------------
| 12456 | 2-US | XS1545
-------------------------------------
What am I missing?
Thank you!
If you build query in Access try:
SELECT Table1.*
FROM Table1
WHERE (((Table1.[ISIN]) In (SELECT ISIN FROM Table2)) AND ((Table1.SecID_by_Bank) Not In (SELECT SecID_by_BANK FROM Table2)));
Or using 1 subquery:
SELECT Table1.*, Table2.ISIN
FROM Table2 RIGHT JOIN Table1 ON Table2.SecID_by_Bank = Table1.SecID_by_Bank
WHERE (((Table1.ISIN) In (SELECT ISIN FROM Table2)) AND ((Table2.ISIN) Is Null));
For query in SQLServer:
select distinct a.SecID_by_Bank, a.[desc], a.isin from #table1 a left join #table2 b
on a.SecID_by_Bank=b.SecID_by_Bank and a.isin=b.isin
join #table2 c on a.isin=c.isin
where b.isin is null

SQL Query to Bring Back where Row Count is Greater than 1

I have two tables.They have the same data but from different sources. I would like to find all columns from both tables that where id in table 2 occurs more than once in table 1. Another way to look at it is if table2.id occurs only once in table1.id dont bring it back.
I have been thinking it would be some combination of group by and order by clause that can get this done but its not getting the right results. How would you express this in a SQL query?
Table1
| id | info | state | date |
| 1 | 123 | TX | 12-DEC-09 |
| 1 | 123 | NM | 12-DEC-09 |
| 2 | 789 | NY | 14-DEC-09 |
Table2
| id | info | state | date |
| 1 | 789 | TX | 14-DEC-09 |
| 2 | 789 | NY | 14-DEC-09 |
Output
|table2.id| table2.info | table2.state| table2.date|table1.id|table1.info|table1.state|table1.date|
| 1 | 789 | TX | 14-DEC-09 | 1 | 123 | TX | 12-DEC-09 |
| 1 | 789 | TX | 14-DEC-09 || 1 | 123 | NM | 12-DEC-09 |
If you using MSSQL try using a Common Table Expression
WITH cte AS (SELECT T1.ID, COUNT(*) as Num FROM Table1 T1
INNER JOIN Table2 T2 ON T1.ID = T2.ID
GROUP BY T1.ID
HAVING COUNT(*) > 1)
SELECT * FROM cte
INNER JOIN Table1 T1 ON cte.ID = T1.ID
INNER JOIN Table2 T2 ON cte.ID = T2.ID
First, I would suggest adding an auto-incrementing column to your tables to make queries like this much easier to write (you still keep your ID as you have it now for relational-mapping). For example:
Table 1:
TableID int
ID int
Info int
State varchar
Date date
Table 2:
TableID int
ID int
Info int
State varchar
Date date
Then your query would be really easy, no need to group, use CTEs, or row_over partitioning:
SELECT *
FROM Table2 T2
JOIN Table1 T1
ON T2.ID = T1.ID
JOIN Table1 T1Duplicate
ON T2.ID = ID
AND T1.TableID <> T1Duplicate.TableID
It's a lot easier to read. Furthermore, there are lots of scenarios where an auto-incrementing ID field is benefitial.
I find this a much simpler way to do it:
select TableA.*,TableB.*
from TableA
inner join TableB
on TableA.id=TableB.id
where TableA.id in
(select distinct id
from TableA
group by id
having count(*) > 1)