MySQL Insert and merge into new Table with Rows from one Table - mysql

I have a table as follows:
id - rowid - value - date
and in each row I have:
1 - 9 - 123 - 03/2013
2 - 10 - 456 - 03/2013
I want to join both rows into one table like this:
id - rowid - value1 value2 - date
1 - 9 - 123 - 456 - 03/2013
I only need from the first table, the rowid 9 as in the example and the value and date.
From the second row I only need the value. I tried union all and multiple selection but with no success effort.
Help would be highly appreciated. Thanks in advance!

--Assumes there are ONLY 2 records in table with same date.
--If not accurate you will end up with only 1 less record per date than you currently have.
--Assumes you only what the lowest RowId recorded.
create table myNewtable as
(SELECT A.RowID, A.Value, B.Value, A.Date
FROM Oldtable A INNER JOIN Oldtable B
on A.Date=B.Date
and A.RowID < B.RowId)
--Now that we know date is date time and is likely different...
but that RowID is always +1 for the ones you want to join
create table myNewtable as
(SELECT A.RowID, A.Value, B.Value, A.Date
FROM Oldtable A
INNER JOIN Oldtable B
on A.RowID = B.RowId-1)

Related

How can I make a WHERE clause restriction dynamic on ID level

I want to create a WHERE clause where the restriction is dynamic depending on the ID and date I am looking for to do a count on the number of rows on an ID level in one table and bring it into another table:
Table A looks like this with several IDs:
ID - Create date
12221 - 12/12/2018
13331 - 12/10/2018
Table B has the following information with several IDs
ID - Date
12221 - 10/10/2018
12221 - 07/06/2017
13331 - 01/20/2019
I now want to do a count of all the rows in Table 2 that have a date in there before the actual signup date per ID. so in the example above it should say:
ID - Count
12221 - 2
13331 - 0
Not sure how to do that in SQL with a WHERE clause. I could potentially bring in the "create date" as a new column in Table B and do a workaround on that (e.g. 1 if date smaller than create date, and 0 if date bigger than create date) and then put that into the WHERE clause, but since I have a ton of data, that is not the ideal solution.
Thank you!
Join the tables and group with the condition on dates:
select b.id, sum(a.createdate is not null) count
from tableb b left join tablea a
on a.id = b.id and b.date < a.createdate
group by b.id
See the demo.
Results:
| id | count |
| ----- | ----- |
| 12221 | 2 |
| 13331 | 0 |
You need to select all records from TableA and a count of records in TableB that have a date that is before the date in TableA:
CREATE TEMPORARY TABLE TableA (ID INT, CreateDate DATETIME);
INSERT INTO TableA VALUES (12221, '2018-12-12'), (13331, '2018-10-12');
CREATE TEMPORARY TABLE TableB (ID INT, DDate DATETIME);
INSERT INTO TableB VALUES (12221, '2018-10-10'), (12221, '2017-06-07'), (13331, '2019-01-20');
SELECT a.ID,
COUNT(b.ID) AS MatchCount
FROM TableA a
LEFT JOIN TableB b ON b.ID = a.ID AND b.DDate < CreateDate
GROUP BY ID;
DROP TABLE TableA;
DROP TABLE TableB;
Note that in my example I have renamed the date column from TableB to DDate.
Output:
ID MatchCount
12221 2
13331 0
In the above SQL, TableB is joined to TableA using the criteria that the ID must be equal and the date must be before the created date. The result set is built by counting the number of rows returned from TableB that match this criteria.
This should give you every id from TableA and the desired count:
SELECT a.id, COUNT(b.id) AS preSignupEntries
FROM TableA AS a
LEFT JOIN TableB AS b ON a.id = b.id AND a.`Create date` > b.`Date`
GROUP BY a.id;
COUNT, like most aggregate functions, ignores NULL values.
Edit: this assumes your "date" fields are actually a date data type; if you are storing them as strings, you'll need to do some parsing.
Edit2: Using an INNER JOIN could be slightly faster if you do not actually care about TableA entries without predated TableB entries.
select a.id, IFNULL((select count(b.id)
from tableb b
where a.id = b.id and b.date < a.createdate
group by b.id ),0) as total
from tablea a
For the scenario the you have a row in table a, but not in table b:
IFNULL function only applies for mysql.
table a
ID - Create date
12221 - 12/12/2018
13331 - 12/10/2018
13336 - 12/10/2018
table b
ID - Date
12221 - 10/10/2018
12221 - 07/06/2017
13331 - 01/20/2019
result
ID MatchCount
12221 2
13331 0
13336 0
try
Select id,Count(id) From TableB Group By ID

Adding one extra row to the result of MySQL select query

I have a MySQL table like this
id Name count
1 ABC 1
2 CDF 3
3 FGH 4
using simply select query I get the values as
1 ABC 1
2 CDF 3
3 FGH 4
How I can get the result like this
1 ABC 1
2 CDF 3
3 FGH 4
4 NULL 0
You can see Last row. When Records are finished an extra row in this format
last_id+1, Null ,0 should be added. You can see above. Even I have no such row in my original table. There may be N rows not fixed 3,4
The answer is very simple
select (select max(id) from mytable)+1 as id, NULL as Name, 0 as count union all select id,Name,count from mytable;
This looks a little messy but it should work.
SELECT a.id, b.name, coalesce(b.`count`) as `count`
FROM
(
SELECT 1 as ID
UNION
SELECT 2 as ID
UNION
SELECT 3 as ID
UNION
SELECT 4 as ID
) a LEFT JOIN table1 b
ON a.id = b.id
WHERE a.ID IN (1,2,3,4)
UPDATE 1
You could simply generate a table that have 1 column preferably with name (ID) that has records maybe up 10,000 or more. Then you could simply join it with your table that has the original record. For Example, assuming that you have a table named DummyRecord with 1 column and has 10,000 rows on it
SELECT a.id, b.name, coalesce(b.`count`) as `count`
FROM DummyRecord a LEFT JOIN table1 b
ON a.id = b.id
WHERE a.ID >= 1 AND
a.ID <= 4
that's it. Or if you want to have from 10 to 100, then you could use this condition
...
WHERE a.ID >= 10 AND
a.ID <= 100
To clarify this is how one can append an extra row to the result set
select * from table union select 123 as id,'abc' as name
results
id | name
------------
*** | ***
*** | ***
123 | abc
Simply use mysql ROLLUP.
SELECT * FROM your_table
GROUP BY Name WITH ROLLUP;
select
x.id,
t.name,
ifnull(t.count, 0) as count
from
(SELECT 1 AS id
-- Part of the query below, you will need to generate dynamically,
-- just as you would otherwise need to generate 'in (1,2,3,4)'
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
) x
LEFT JOIN YourTable t
ON t.id = x.id
If the id does not exist in the table you're selecting from, you'll need to LEFT JOIN against a list of every id you want returned - this way, it will return the null values for ones that don't exist and the true values for those that do.
I would suggest creating a numbers table that is a single-columned table filled with numbers:
CREATE TABLE `numbers` (
id int(11) unsigned NOT NULL
);
And then inserting a large amount of numbers, starting at 1 and going up to what you think the highest id you'll ever see plus a thousand or so. Maybe go from 1 to 1000000 to be on the safe side. Regardless, you just need to make sure it's more-than-high enough to cover any possible id you'll run into.
After that, your query can look like:
SELECT n.id, a.*
FROM
`numbers` n
LEFT JOIN table t
ON t.id = n.id
WHERE n.id IN (1,2,3,4);
This solution will allow for a dynamically growing list of ids without the need for a sub-query with a list of unions; though, the other solutions provided will equally work for a small known list too (and could also be dynamically generated).

Slow query on update using select count(*)

I have to count how many times a number from table2 occurs between the number in range table2.a and table2.b
i.e. we wanna know how many times we have this : a < start < b
I ran the following query :
UPDATE table2
SET occurrence =
(SELECT COUNT(*) FROM table1 WHERE start BETWEEN table2.a AND table2.b);
table2
ID a b occurrence
1 1 10
2 1 20
3 1 25
4 2 30
table1
ID start col1 col2 col3
1 1
2 7
3 10
4 21
5 25
6 27
7 30
table2 as
3 indexes on a, b and occurrence
1567 rows (so we will SELECT COUNT(*) over table2 1567 times..)
ID column as PK
table1 as
1 index on start
42,000,000 rows
Column start was "ordered by column start"
ID column as PK
==> it took 2.5hours to do 2/3 of it. I need to speed this up... any suggestions ? :)
You could try to add the id column to the index on table 1:
CREATE INDEX start_index ON table1 (start,id);
And rewrite the query to
UPDATE table2
SET occurrence =
(SELECT COUNT(id) FROM table1 WHERE start BETWEEN table2.a AND table2.b);
This is called "covering index": http://www.simple-talk.com/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/
-> The whole query on table 1 can be served through the data in the index -> no additional page lookup for the actual record.
Use a stored procedure. Keep the result from COUNT in a local variable, then use it to run the UPDATE query.
I will do this
// use one expensive join
create table tmp
select table2.id, count(*) as occurrence
from table1
inner join table1
on table1.start between table2.a and table2.b
group by table1.id;
update table2, tmp
set table2.occurrence=tmp.occurrence
where table2.id=tmp.id;
I think count(*) makes the database read the data rows when in your case it only needs to read the index. Try:
UPDATE table2
SET occurrence =
(SELECT COUNT(1) FROM table1 WHERE start BETWEEN table2.a AND table2.b);

Comparing a column against an entire table of ranges?

Sorry if this has been asked before, I've searched and have been unable to find any answers.
I have 2 tables in a DB, TableA has a column we'll call ID (a 4-digit integer), and TableB has 2 columns of 4-digit integers that form a range.
What I would like to do is check to see which ID's can be found in any range, so that if ID had
1
5
7
9,
and TableB had ranges
4-6,
100-101,
and 3000-4000, 5 would be properly matched as belonging to a range. Any ideas?
Try this:
SELECT *
FROM TableA a
WHERE EXISTS
(
SELECT 1
FROM TableB b
WHERE a.ID BETWEEN b.ID1 AND b.ID2
)

find the output mysql query

I have a table name T1 having only one Column name Col1 having rows –
Col1
a
b
c
And another table name T2 also having only one Column name Col1 having rows –
Col1
x
y
z
Now I want record like
Col1--Col2
a------x
b------y
c------z
I am using mysql.
Thanks in advance!!
create table T1(col1 varchar(10));
insert T1 values ('a'),('b'),('c');
create table T2(col2 varchar(10));
insert T2 values ('x'),('y'),('z');
select A.col1, B.col2 from
(select #r:=#r+1 rownum, col1 from (select #r:=0) initvar, T1) A,
(select #s:=#s+1 rownum, col2 from (select #s:=0) initvar, T2) B
where A.rownum=B.rownum
Because there is no ORDER BY clause, you are depending on luck and convention for the row numbering to be according to the order inserted. It may not always be the case.
In your example, if you want to join the tables to get row results like this:
Row 1 - A,X
Row 2 - B,Y
Row 3 - C,Z
..then you will have to add a common field that you can JOIN the two tables on.
If you want to be able to return results from both tables like this:
Row 1 - A
Row 2 - B
Row 3 - C
Row 4 - X
Row 5 - Y
Row 6 - Z
.. then you will need to use a UNION:
(SELECT Col1 FROM T1) UNION (SELECT Col1 FROM T2)