I have one table (in phpmyadmin) with the following fields and structure:
Table 1
id | sponsor
1 | -1
2 | 1
3 | 1
4 | 2
5 | 4
6 | 4
Now i want to insert data from above table into new table as below:
Table 2
id | children
1 | 2,3
2 | 4
3 |
4 | 5,6
5 |
6 |
Actually this is Tree structure, which i have saved in mysql database.
I have already written a script in php but as there are more then 100K rows in table 1 so its taking too much time. Please tell me an efficient sql query to do this task quickly.
Query:
SQLFIDDLE Example
SELECT
t1.id,
(SELECT group_concat(id separator ', ')
FROM table1 t2
WHERE t2.sponsor = t1.id) AS children
FROM table1 t1
GROUP BY t1.id
Result:
| ID | CHILDREN |
-----------------
| 1 | 2, 3 |
| 2 | 4 |
| 3 | (null) |
| 4 | 5, 6 |
| 5 | (null) |
| 6 | (null) |
Insert Statement:
INSERT INTO table2
SELECT
t1.id,
(SELECT group_concat(id separator ', ')
FROM table1 t2
WHERE t2.sponsor = t1.id) AS children
FROM table1 t1
GROUP BY t1.id
This is similar to #Justin's answer but uses a left join instead of a correlated subquery:
INSERT INTO Table2 (id, children)
SELECT
sp.id,
GROUP_CONCAT(ch.id) AS children
FROM Table1 sp
LEFT JOIN Table1 ch ON sp.id = ch.sponsor
GROUP BY t1.id
;
A demonstration of the SELECT statement's result can be found (and played with) at SQL Fiddle (the schema having been borrowed from Justin).
One of your SELECT elements should be a GROUP_CONCAT(...) as column, which will concatenate those values separated with commas. If you want to filter by one of those values, you can use GROUP BY -whatever- HAVING find_in_set( -number- , column )
See if the following helps
INSERT INTO table2
SELECT sponsor, GROUP_CONCAT(id)
FROM table1
GROUP BY id
Related
why I can't Select a row of a table with an unequal concat construction? I'll show you an example.
Table1
| id | area |
| 1 | items_labeling_small |
| 2 | items_labeling_big |
Table2
| id | area | kat |
| 1 | small | labeling |
| 2 | big | labeling |
SELECT Table1.area FROM Table1, Table2 WHERE Table1.area != CONCAT('items_', Table2.kat, '_', Table2.area)
No results have to be shown, because both are matching with the concat construction. But they're shown in result. I've no idea why.. and how I can change the query that it works.
They are show because each row don't match the other so you have the rows that not match
SELECT Table1.area
FROM Table1
INNER JOIN Table2 ON Table1.area != CONCAT('items_', Table2.kat, '_', Table2.area)
could be you want a not in
SELECT Table1.area
FROM Table1
where Table1.area NOT IN (
SELECT CONCAT('items_', Table2.kat, '_', Table2.area)
FROM Table2
)
and as a suggestion you should not use the (old) implict join sintax based on where clause ...use explicit join sintax ..
I am new to mysql and I am attempting to get all ID from another table where ID is equal to ID from table 1 and another conditions.
Table 1
+---------------+
| ID model line |
+---------------+
| 1 XX C1 |
| 2 AA C3 |
| 3 SS C1 |
+---------------+
Table 2 ( So if my query is ID = 1 AND model = XX GROUP BY line the total rows from table 2 will return 3 since ID 1,4 and 5 is true.
+----------------------------+
| ID InspectionID model line |
+----------------------------+
| 1 1 XX C1 |
| 2 1 AA C3 |
| 3 1 SS C1 |
| 4 1 XX C2 |
| 5 1 XX C4 |
+----------------------------+
So far i have this query inside a PHP while loop it return what i wanted but the query is really slow.
$query = "SELECT * FROM table2 WHERE inspectionID = '$ID' AND model = '$modelID' GROUP BY line
So i think the best way is to join table1 and table2 and add a column total
sadly my knowledge on mysql and joining table is limited, any suggestions is appreciated.
my target is to create below.
+---------------------+
| ID model line total |
+---------------------+
| 1 XX C1 3 |
| 2 AA C3 0 |
| 3 SS C1 0 |
+---------------------+
Pretty simple join and aggregation. working demo
(note demo includes both answers so far and results.)
We left join so we keep all records from table 1 and join to table 2 to get records matching from table 1. We set the limit on model on the join itself so the filtering is applied to the table2 before the join occurs. thus the count will only include model XX and all other counts for models will be zero.
SELECT T1.ID, T1.Model, T1.Line, count(T2.ID)
FROM table1 T1
LEFT JOIN Table2 T2
on T1.Model = T2.Model
and T2.Model = 'XX'
GROUP BY T1.ID, T1.Model, T1.Line
ORDER BY T1.ID
Just create an SQL View:
CREATE VIEW TABLE_1_2_VIEW AS
SELECT A.id, A.model, A.line, B.inspectionID, COUNT(B.ID) Total
FROM table_1 A LEFT JOIN table_2 B
ON A.model=B.model
GROUP BY A.id, A.model, A.line, B.inspectionID
ORDER BY A.id, A.model, A.line;
You can query the data from this view as if it were a table.
SELECT id, model, line, IF(model='XX', Total, 0) Total
FROM TABLE_1_2_VIEW
WHERE inspectionID=1;
Just that the data in this view would not be updatable.
Example Table Structure
Table 1
ID | Name | Price
-----------------------------
1 | Casio | 30
2 | Titan | 40
Table 2
ID | Place | Price
-----------------------------
1 | Cali | 30
2 | Mexi | 10
Operation to perform:
Table1(Price) - Table2(Price) for ID = 1
New Table 1
ID | Name | Price
-----------------------------
1 | Casio | 0
2 | Titan | 40
ID matches in both tables
You should consider another database design to handle this case.
But to answer your question, you can create a view :
create view Differences2 as (
select t1.id, t1.price - t2.price
from t1, t2
where t1.id = t2.id
)
As you told both table will have same ID column you can use following query.
SELECT table1.ID, table1.Name, (table1.Price-table2.Price) AS Price
FROM table1
INNER JOIN table2 ON table1.ID = table2.ID
If you want to update record you can use following:
UPDATE table1
INNER JOIN table2 ON table1.ID = table2.ID
SET table1.Price = (table1.Price-table2.Price)
[TABLE 1]
+---------+---------+------------------+
| post_id | user_id | description |
+---------+---------+------------------+
| 1 | 1 | Sample post 1 |
| 2 | 1 | Sample post 2 |
| 3 | 2 | Sample post 3 |
| 4 | 2 | Sample post 4 |
| 5 | 3 | Sample post 5 |
+---------+---------+------------------+
[TABLE 2]
+---------+---------+---------+
| id | user_id | post_id |
+---------+---------+---------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
+---------+---------+---------+
When the USER_ID 1 in TABLE 1 already existed in TABLE 2 with its respected POST_ID, it should not be part of return select query. Instead, it would return POST_ID 2,3,4,5 in TABLE 1.
When the USER_ID 2 in TABLE 1 already existed in TABLE 2 with its respected POST_ID, the expected return select query would be POST_ID 1,3,4,5 in TABLE 1 as well as the other id's.
Thanks in advance guys! :)
Looks like an anti join pattern could achieve the specified result.
SELECT t.post_id
, t.user_id
, t.description
FROM `[Table 1]` t
LEFT
JOIN `[Table 2]` u
ON u.post_id = t.post_id
AND u.user_id = ?
WHERE u.post_id IS NULL
ORDER BY t.post_id
The ? is the placeholder character for specifying a userid.
This essentially says return all rows from Table 1 along with matching rows from Table 2, but (here's the trick) the WHERE clause says to exclude all rows that found a matching row in Table 2. Leaving only rows from Table 1 that don't have a match in Table 2.
The anti join takes a little bit of effort to get your brain wrapped around, but once you get it, it's an invaluable tool to keep handy in the SQL toolbelt.
There are other query patterns that will return an equivalent result, such as a NOT EXISTS (correlated subquery) or the more common NOT IN (subquery). (With the NOT IN, be careful that the subquery doesn't return any NULL values.)
EDIT
Removed the condition u.user_id = t.user_id from the join predicate. Looks like the user_id in [Table 1] is the "author" of the post. And has no relation to whether a user has "viewed" a post or not.
Base on your sample data, because USER_ID 1 in TABLE 1 already existed in TABLE 2 with its respected POST_ID, it should return POST_ID 2,3,4,5.
Query:
SELECT t1.* FROM table2 t2
RIGHT OUTER JOIN table1 t1
ON t2.user_id = t1.user_id AND t2.post_id = t1.post_id
WHERE t2.user_id IS NULL
Final Result:
post_id user_id description
2 1 Sample post 2
3 2 Sample post 3
4 2 Sample post 4
5 3 Sample post 5
Is this what you are looking for?
I have 2 database tables:
Table 1:
+---------+-------+-------------+
| Page | Title | Description |
+---------+-------+-------------+
| Apple | ..... | ........... |
| Orange | ..... | ........... |
| Pear | ..... | ........... |
| Grapes | ..... | ........... |
+---------+-------+-------------+
Table 2:
+----------+-------------+
| Link | Page |
+----------+-------------+
| Website1 | Apple |
| Website2 | Orange |
| Website3 | Apple |
| Website4 | Orange |
| Website5 | Apple |
| Website6 | Pear |
| Website7 | Apple |
| Website8 | Grapes |
| Website9 | Grapes |
+----------+-------------+
I want to know/return how many pages from Table 1 are referenced in Table 2 and how many times they are referenced. (I DON'T want to know how many times EACH page in Table 1 is referenced in Table 2).
So in this example:
1 page is referenced 1 time (Pear),
2 pages are referenced 2 times (Grapes and Orange) &
1 page is referenced 4 times.
What kind of SQL statement would I use to get this?
Following query should do..
SELECT COUNT(1) NoOfPages,CNT ReferencedTimes
FROM
(
SELECT T2.PAGE,COUNT(1) CNT
FROM TABLE1 T1 INNER JOIN TABLE2 T2 ON T1.PAGE = T2.PAGE
GROUP BY T2.PAGE
)T
GROUP BY CNT
I think the following statement will fit:
SELECT count(*) FROM Table2 WHERE (Table2.Page IN (SELECT Page FROM Table1));
Use This query
Select table2.page,cnt(table2.page)
from table1 inner join table2
On table1.Page=table2.Page group by table2.page
SELECT (GROUP_CONCAT(DISTINCT page)) AS Page,page_count
FROM
(SELECT table1.Page as page,COUNT(*) as page_count
FROM table1 INNER JOIN table2 ON table1.Page=table2.Page
GROUP BY table1.Page)
as T GROUP BY page_count
Hope this helps
If what you are seeking is X page was referenced N times, the below query will achieve that:
SELECT COUNT(t1.page), t2.count
FROM table1 t1
INNER JOIN (SELECT page,COUNT(*) AS count FROM table2 GROUP BY page) t2 ON t1.page=t2.page
GROUP BY t2.count
Try this query, it will make a left join and tell you how many times item is referenced in table2, if count is zero than no reference in the other table
SELECT table1.Page, count(table2.Page) as count
FROM table1
LEFT JOIN table2 ON table2.Page = table1.Page
GROUP BY table1.Page