Joining tables with different amount of rows - mysql

I would like to join two tables.
One table has the following structure:
ID1, ID2, Type, Birth date, sex
where ID2 is unique but the same ID1 may have two different ID2's - so two rows in this table.
What I would like to do is, add these values to another table BUT for ID1's with two ID2's I wouldn't like to have two rows but add another column like type2, birth date2, sex2 and fill these values only for ID1s which are not unique.
I tried something like this:
In a first step I already added all ID1s to the table where type=1. There are several ID1s left, where type=2. Now I would like to add these to the table like this
create table VB_VT_hvgruppe_LV_PRV_VPVT_HILF as
select
a . *,
c.ns5_vptypid as ns5_vptypid2,
c.ns5_gebdat as ns5_gebdat2,
c.ns5_sex as ns5_sex2
from
VB_VT_hvgruppe_LV_PRV_VPVT a
join,
(select
b.ns5_vpvt_ordinal, b.ns5_vptypid, b.ns5_gebdat, b.ns5_sex
from
lfglende.ns5_vpvt1 b
where
b.ns5_vptypid = '2') as c ON a.ns5_vb_ordinal = b.ns5_vpvt_ordinal
where
a.ns5_vb_ordinal = c.ns5_vpvt_ordinal
but this did not work.
Could you help me out?

You have an error in your syntax:
VB_VT_hvgruppe_LV_PRV_VPVT a join, (select
shouldn't have the comma - try this:
create table VB_VT_hvgruppe_LV_PRV_VPVT_HILF as
select
a . *,
c.ns5_vptypid as ns5_vptypid2,
c.ns5_gebdat as ns5_gebdat2,
c.ns5_sex as ns5_sex2
from
VB_VT_hvgruppe_LV_PRV_VPVT a
join
(select
b.ns5_vpvt_ordinal, b.ns5_vptypid, b.ns5_gebdat, b.ns5_sex
from
lfglende.ns5_vpvt1 b
where
b.ns5_vptypid = '2') as c ON a.ns5_vb_ordinal = b.ns5_vpvt_ordinal
where
a.ns5_vb_ordinal = c.ns5_vpvt_ordinal

If you know there are at most two values of ID2 for any particular ID1, then you can join the table to itself, getting the lower value on the "left" and the higher value on the "right".
select T1.ID1, T1.ID2, T1.Type, T1.Birthdate, T1.sex
T2.ID2 as T2ID2, T2.Type as TYPE2, T2.Birthdate as Birthdate2, T2.sex as sex2
from mytable t1
left join mytable t2
on t1.ID1=T2.ID1 and t1.ID2<t2.ID2
If you don't want the nulls in the T2 values, where there's just one record, use COALESCE() on each of those fields.

Related

MySQL: selecting rows by two of three primary keys

I am searching for exactly the opposite of what Jonathan was searching in this example:
How to select multiple rows by multi-column primary key in MySQL?
Having 3 columns as a primary key (the 3rd is a date), I want to select all of them without the most recent one. And if there is no second entry for a combination of the first two primary values, I don't want to select it at all. Think of it as a kind of versioning. The table-structure contains more columns than those three and i want to select the whole rows.
Looks something like that:
{ID1 | ID2 | DATE} | more columns ...
Pseudocode:
SELECT * FROM table WHERE (first and second primary value are the same and exist more than once) AND NOT MAX(date)
:D
I want to output the data of all previous versions of the row, not including the most recent one.
Thanks in advance for any suggestions!
Break down the problem into steps:
Pseudo logic:
Get a data set with the records we want to exclude
now exclude that data set from the entire set
Step 1: Get a dataset of only those records having a max data for ID1, ID2
SELECT ID1, ID2, Max(date) date
FROM Table
GROUP BY ID1, ID2
Step 2: Now use that data set to identify/eliminate the records you don't want.. a not exists is likely the fastest.
Faster...
SELECT A.*
FROM TABLE A
WHERE NOT EXISTS
(SELECT 1
FROM (SELECT ID1, ID2, Max(date) date
FROM Table
GROUP BY ID1, ID2) B
WHERE A.ID1 = B.ID1
and A.ID2 = B.ID2
and A.Date = B.Date)
or as a self outer join on a subset, slower but gives you access to additional details on subset if needed. (not much use in this example but could be useful in other circumstances)
The left join to the data set shows those that match on the max date, so all other records would be null, which is the data set you're after...
SELECT A.*
FROM TABLE A
LEFT JOIN (SELECT ID1, ID2, Max(date) date
FROM Table
GROUP BY ID1, ID2) B
on A.ID1 = B.ID1
and A.ID2 = B.ID2
and A.Date = B.Date
WHERE B.ID1 is null

SQL Join 2 tables with almost same field

I need to join two tables in SQL. There are no common fields. But the one table have a field with the value krin1001 and I need it to be joined with the row in the other table where the value is 1001.
The idea behind the joining is i have multiple customers, but in the one table there customer id is 'krin1001' 'krin1002' and so on, in this table is how much they have sold. In the other table there customer is is '1001' '1002' and so on, and in this table is there name and adress and so on. So it will always be the first 4 charakters i need to strip from the field before matching and joining. It might not always be 'krin' i need it to work with 'khjo1001' also, and it still needs to join on the '1001' value from the other table.
Is that possible?
Hope you can help me.
You need to use substring:
ON SUBSTRING(TableA.Field, 5, 4) = TableB.Field
Or Right:
ON RIGHT(TableA.Field, 4) = TableB.Field
You can also try to use CHARINDEX function for join operation. If value from table1 contains value from table2 row will be included in result set.
;WITH table1 AS(
SELECT 'krin1001' AS val
UNION ALL
SELECT 'xxx'
UNION ALL
SELECT 'xyz123'
),
table2 AS(
SELECT '1001' AS val
UNION ALL
SELECT '12345'
UNION ALL
SELECT '123'
)
SELECT * FROM table1 AS t
JOIN table2 AS T2 ON CHARINDEX(T2.val, T.val) > 0
Use it as:
SELECT
*
FROM table t1
INNER JOIN table t2 ON RIGHT(t1.col1, 4) = t2.col1;

I wanted to know the command to check if all the values in one field of a table is present in another table under a different field name

I have 2 tables. I want to find out whether the values present in the first table is there in another table with a different field name.
Here is how it looks,
Table1
BillNo
43529179
43256787
35425676
25467778
24354758
45754748
Table2
BNo
113104808
25426577
268579679
2542135464
252525232
235263663
I have 137 records in table1 that needs to be checked against table2.
Instead of doing it one by one using the following command,
Select * from Table2 where BNo = '43529179';
This gives the result for just the mentioned value. Is there a way to check for all the values in a single query?
Thanks!
You can use a sub-select to compare against:
Select * from Table2 where BNo IN (SELECT BillNo FROM Table1);
That will "evalaute" to something like Select * from Table2 where BNo IN (113104808, 25426577, 268579679, 2542135464, 252525232, ...);
Join the tables, and check how many matching records there are:
select
count(*) as Matches
from
Table1 as t1
inner join Table2 as t2 on t2.BNo = t1.BillNo
You can also use a left join to pick out the records in table 1 that has no matching record in table 2:
select
t1.BillNo
from
Table1 as t1
left join Table2 as t2 on t2.BNo = t1.BillNo
where
t2.BNo is null

Copy rows if value exists x amount of times

I have two tables Board1 and Board2 with the identical structure. They both have a primary index column of id. I have a THIRD table called Table1, which has a non-indexed column board_id, where the same board_id occurs multiple times. board_id always corresponds to an id in Board1. Board2 is currently empty, and I want to add rows from Board1, but only where the same board_id occurs at least six times in Table1. Table1 will be changing periodically, so I'll be needing to do the query in the future, but without doubling id rows which are already in Board2.
So to recap:
There are three tables: Board1, Board2, and Table1. I want to copy rows from Board1 to Board2, but only where the id in the Board1 occurs (at least) six times in Table1 as `board_id'.
I'd appreciate any help!
EDIT: I'm dreadfully sorry, but I realized I made a huge mistake in my question. I've rewritten it to reflect what I actually needed. I'm truly sorry.
You can do it like this
INSERT INTO Table2
SELECT
id,
board_id
FROM (SELECT
b.id,
b.board_id,
bl.Count
FROM board as b
LEFT JOIN (SELECT
board_id,
COUNT(board_id) as `Count`
FROM board
GROUP BY board_id) as bl
on bl.board_id = b.board_id
group by b.id
having bl.Count >= 6) as L
If you need more columns you can select them in inner and outer queries.
Fiddle Demo for Select
Here is what you asked for, with fiddle
INSERT Table2
SELECT
*
FROM
Table1
JOIN
(
SELECT
Board_Id,
count(*) cnt
FROM
Table1
GROUP BY
Board_Id
) BoardIds
ON BoardIds.Board_Id = Table1.Board_Id
WHERE
BoardIds.cnt > 5
AND
NOT EXISTS (SELECT id FROM Table2 WHERE Table2.id = Table1.id)
Try something like the below:
Add your column names where specified (excluding any ID columns), as I'm assuming each row will have a unique ID, so you won't be able to GROUP and COUNT by doing SELECT * FROM Table1
You may need to test / validate this
INSERT INTO Board2 (Your Column Names)
SELECT (Your Column Names)
FROM Board1
WHERE id (IN (SELECT board_id
FROM Table1
GROUP BY (board_id)
HAVING (COUNT(*) >= 6))
AND board_id NOT IN(SELECT DISTINCT board_id FROM Board2)

Insert missing records from one table to another using mysql

I don't know why I am confused with this query.
I have two table: Table A with 900 records and Table B with 800 records. Both table need to contain the same data but there is some mismatch.
I need to write a mysql query to insert missing 100 records from Table A to Table B.
In the end, both Table A and Table B should be identical.
I do not want to truncate all the entries first and then do a insert from another table. So please any help is appreciated.
Thank you.
It is also possible to use LEFT OUTER JOIN for that. This will avoid subquery overhead (when system might execute subquery one time for each record of outer query) like in John Woo's answer, and will avoid doing unnecessary work overwriting already existing 800 records like in user2340435's one:
INSERT INTO b
SELECT a.* FROM a
LEFT OUTER JOIN b ON b.id = a.id
WHERE b.id IS NULL;
This will first select all rows from A and B tables including all columns from both tables, but for rows which exist in A and don't exist in B all columns for B table will be NULL.
Then it filter only such latter rows (WHERE b.id IS NULL),
and at last it inserts all these rows into B table.
I think you can use IN for this. (this is a simpliplification of your query)
INSERT INTO table2 (id, name)
SELECT id, name
FROM table1
WHERE (id,name) NOT IN
(SELECT id, name
FROM table2);
SQLFiddle Demo
AS you can see on the demonstration, table2 has only 1 records but after executing the query, 2 records were inserted on table2.
If it's mysql and the tables are identical, then this should work:
REPLACE INTO table1 SELECT * FROM table2;
This will insert the missing records into Table1
INSERT INTO Table2
(Col1, Col2....)
(
SELECT Col1, Col2,... FROM Table1
EXCEPT
SELECT Col1, Col2,... FROM Table2
)
You can then run an update query to match the records that differ.
UPDATE Table2
SET
Col1= T1.Col1,
Col2= T1.Col2,
FROM
Table T1
INNER JOIN
Table2 T2
ON
T1.Col1 = T2.Col1
Code also works when a group by and having clauses are used. Tested SQL 2012 (11.0.5058) Tab1 is source with new records, Tab 2 is the destination to be updated. Tab 2 also has an Identity column. (Yes folks, real world is not as neat and clean as the lab assignments)
INSERT INTO Tab2
SELECT a.T1,a.T2,a.T3,a.T4,a.Val1,a.Val2,a.Val3,a.Val4,-9,-9,-9,-9,MIN(hits) MinHit,MAX(hits) MaxHit,SUM(count) SumCnt, count(distinct(week)) WkCnt
FROM Tab1 a
LEFT OUTER JOIN Tab2 b ON b.t1 = a.t1 and b.t2 = a.t2 and b.t3 = a.t3 and b.t4 = a.t4 and b.val1 = a.val1 and b.val2 = a.val2 and b.val3 = a.val3 and b.val4 = a.val4
WHERE b.t1 IS NULL or b.Val1 is NULL
group by a.T1,a.T2,a.T3,a.T4,a.Val1,a.Val2,a.Val3,a.Val4 having MAX(returns)<4 and COUNT(distinct(week))>2 ;