Copy rows if value exists x amount of times - mysql

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)

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

SQL Select max value by grouping two columns

Here is my sql fiddle.
http://sqlfiddle.com/#!2/7f0780/1/0
I seem to have a problem that when I group two columns to get the max() value it returns the wrong associated data.
You will see the id's are incorrect.
Could someone please help me.
create table table1 (id int,id1 int, id2 int, version int);
insert into table1 values
(1,7,9,1),
(2,7,9,2),
(3,7,9,3),
(4,7,9,4),
(5,9,7,5),
(6,9,7,6);
SELECT max(version),id
FROM table1
group BY
id1,id2
MAX(VERSION) ID
4 1
6 5
Your SQL Query is:
SELECT max(version), id
FROM table1
group BY id1, id2
Note that you are grouping by two columns. But, you are selecting neither of them in the select statement. Instead, you have id. The value of id comes from an arbitrary row, as explained in the MySQL documentation. My advice is to never use this extension, unless you really, really understand what you are doing.
If you want the id associated with the maximum value, you can do it using not exists:
select *
from table1 t
where not exists (select 1
from table1 t1
where t1.id1 = t.id1 and
t1.id2 = t.id2 and
t1.version > t.version
);
That is, select all rows from table1 where the version for the id1/id2 pair has no larger value.
EDIT:
I should add that for performance reasons, an index on table1(id1, id2, version) will help this query a lot.

Get last but one row for each ID

I am using query like
select * from audittable where a_id IN (1,2,3,4,5,6,7,8);
For each ID its returning 5-6 records. I wanted to get the last but one record for each ID.
Can i do this in one sql statement.
Try this query
SELECT
*
FROM
(SELECT
#rn:=if(#prv=a_id, #rn+1, 1) as rId,
#prv:=a_id as a_id,
---Remaining columns
FROM
audittable
JOIN
(SELECT #rn:=0, #prv:=0) t
WHERE
a_id IN (1,2,3,4,5,6,7,8)
ORDER BY
a_id, <column> desc)tmp --Replace column with the column with which you will determine it is the last record
WHERE
rId=1;
If your database is having DateCreated or any column in which you are saving the DateTime as well like when your data is inserted for a particular row then you may use query like
select at1.* from audittable at1 where
datecreated in( select max(datecreated) from audittable at2
where
at1.id = at2.id
order by datecreated desc
);
You may also use LIMIT function as well.
Hope you understand and works for you.
In SQLite, you have the columns a_id and b. For each a_id you get a set of b's. Let you want
to get the latest/highest (maximum in terms of row_id, date or another naturally increasing index) one of b's
SELECT MAX(b), *
FROM audittable
GROUP BY a_id
Here MAX help to get the maximum b from each group.
Bad news that MySQL doesn't associate MAX b with other *-columns of the table. But it still can be used in case of simple table with a_id and b columns!