I have got 3 tables:
+-----+----------+ +-----+----------+-------+ +-----+----------+-------+
| id | A_id | | A_id| B_id | value | | B_id| B_id_ | value |
+-----+----------+ +-----+----------+-------+ +-----+----------+-------+
| 1| 5| | 5| 1| aa| | 1| 2| zzxx|
+-----+----------+ +-----+----------+-------+ +-----+----------+-------+
| 2| 3| | 3| 3| bb| | 2| | vvyy|
+-----+----------+ +-----+----------+-------+ +-----+----------+-------+
| 3| 4| bbll|
+-----+----------+-------+
| 5| | oopp|
+-----+----------+-------+
| 4| 5| mmnn|
+-----+----------+-------+
What SELECT statement i need to use, so that output would look like this(table3 can be up to 4 levels deep into it self):
+----+------------------------------+
| id | value |
+----+------------------------------+
| 1| aa\zzxx\vvyy|
+----+------------------------------+
| 2| bb\bbll\mmnn\oopp|
+----+------------------------------+
As i don't have much experience with DB and SQL, this is hard for me. And I have no vision about how to do this.
This has to be done in MySQL. Hardest thing as i have read is the recursive query in MySQL since it doesn't exist, so people have to simulate it. I have read some SO topics about the recursive Query, but i understood that's not for me.
Any help is appreciated.
By hard and fast learning I managed to solve my problem. Code below.
SELECT DISTINCT
OTHER.DATA,
concat(
'/',ifnull(t4.value,''), CASE WHEN (t4.value is NULL) then '' else '/' END,
ifnull(t3.value,''), CASE WHEN (t3.value is NULL) then '' else '/' END,
ifnull(t2.value,''), CASE WHEN (t2.value is NULL) then '' else '/' END,
ifnull(t1.value,''), CASE WHEN (t1.value is NULL) then '' else '/' END,
table2.value
) as 'My Column name'
FROM
table1
LEFT JOIN table2 ON
(table1.A_id = table2.A_id)
LEFT JOIN table3 as t1 ON
(t1.B_id = table2.B_id)
LEFT JOIN table3 AS t2 ON
(t2.B_id = t1.B_id_)
LEFT JOIN table3 AS t3 ON
(t3.B_id = t2.B_id_)
LEFT JOIN table3 AS t4 ON
(t4.B_id = t3.B_id_)
Big Thanks to #Damodaran and his solution for recursive query.
How to create a MySQL hierarchical recursive query
Be careful with using this code, as I have used it for DB, which is only queried for data. So this approach might be slow on other different usage. If you use this, I suggest you to think about indexing some fields.
Related
Solution:
SELECT s.scheme_code ,
ROUND(SUM(m.running_years) * 1.0/NULLIF(COUNT(DISTINCT m.manager_id),0),2) AS 'Average year of experience'
FROM scheme s JOIN managing_body m
ON m.manager_id = s.scheme_manager_id
GROUP BY s.scheme_code;
Table: managing_body
manager_id|manager_name|running_years|
----------|------------|-------------|
51|James | 5|
52|Cork | 3|
53|Paul | 4|
54|Adam | 3|
55|Hense | 4|
56|Peter | 2|
Table : scheme
scheme_code|scheme_manager_id|
-----------|-----------------|
1001| 51|
1001| 53|
1001| 54|
1001| 56|
1002| 51|
1002| 55|
1003| 51|
1004| 52|
Output:
scheme_code|Average year of experience|
-----------|--------------------------|
1001| 3.50|
1002| 4.50|
1003| 5.00|
1004| 3.00|
https://www.w3resource.com/sql-exercises/challenges-1/sql-challenges-1-exercise-32.php
this is the link if anyone wants to see the table and query.
ROUND(SUM(m.running_years) * 1.0/NULLIF(COUNT(DISTINCT m.manager_id),0),2) - I do not clearly understand this part
I am have a source MySql table. I have to export the date to Hive for analytical purpose. Initially when the data size in MySQL was less full export of Mysql data to Hive was not an issue using Sqoop.
Now as my data size has grown how can I take incremental update of MySql data to hive?
You can use sqoop for incremental update, Sqoop documentation is good, here is the link
https://sqoop.apache.org/docs/1.4.2/SqoopUserGuide.html#_incremental_imports
This is an example on incremental update using hive/spark.
scala> spark.sql("select * from table1").show
+---+---+---------+
| id|sal|timestamp|
+---+---+---------+
| 1|100| 30-08|
| 2|200| 30-08|
| 3|300| 30-08|
| 4|400| 30-08|
+---+---+---------+
scala> spark.sql("select * from table2").show
+---+----+---------+
| id| sal|timestamp|
+---+----+---------+
| 2| 300| 31-08|
| 4|1000| 31-08|
| 5| 500| 31-08|
| 6| 600| 31-08|
+---+----+---------+
scala> spark.sql("select b.id,b.sal from table1 a full outer join table2 b on a.id = b.id where b.id is not null union select a.id,a.sal from table1 a full outer join table2 b on a.id = b.id where b.id is null").show
+---+----+
| id| sal|
+---+----+
| 4|1000|
| 6| 600|
| 2| 300|
| 5| 500|
| 1| 100|
| 3| 300|
+---+----+
Hope this logic is gonna work for you.
I'm storing the records in hierarchy.
Ex.
Account -> Hospital -> Department
Account -> Hospital -> Department -> Section
I'm storing the association of all the records in following manner.
+------+---------------+----------+---------------+-----------+
| Id | ParentType | ParentId | Child Type | ChildId |
+------+---------------+----------+---------------+-----------+
| 1| account| 1| hospital| 10|
| 2| account| 1| hospital| 20|
| 3| hospital| 10| department| 100|
| 4| hospital| 10| department| 101|
| 5| department| 100| device| 1000|
| 6| department| 101| device| 1001|
| 6| department| 101| device| 1002|
| 1| account| 2| hospital| 30|
| 2| account| 2| hospital| 40|
| 3| hospital| 30| department| 200|
| 4| hospital| 40| department| 201|
| 5| department| 200| section| 5000|
| 5| department| 200| section| 5001|
| 6| section| 5000| device| 2001|
| 6| section| 5001| device| 2002|
+------+---------------+----------+---------------+-----------+
So, account with id 1, follows first hierarchy; whereas account with id 2 follows second hierarchy.
I need to fetch the records for the given level.
Ex.
Get all the devices belonging to account with id = 1
Get all the devices belonging to department with id = 200 and account with id = 2
and so on.
I can retrieve these with queries like:
First query:
SELECT a3.ChildType, a3.ChildId FROM association_lookup a1 -- [got hosp level]
JOIN association_lookup a2 ON a2.parentId = a1.ChildId -- [got dept level]
JOIN association_lookup a3 ON a3.parentId = a2.ChildId AND a3.ParentType = a2.ChildType -- [got device level]
WHERE a1.ParentId = 1 AND a1.ParentType = 'account'
AND a3.ChildType = 'device'
I can make this as dynamic query with self joins equal to level difference - 1. i.e. account level = 0, device level = 3; hence 2 joins.
But now, if I want to associate device against hospital level instead of department level; like:
| xx| hospital| 10| device| 1003|
then for the same query this device will be skipped and only the devices associated with department level will be returned. How can I get all the devices (i.e. under both hospital level and department level).
That is a horrible way to store data.
I suggest restructuring and creating separate tables each entity.
I.e. create table account, create table hospital ...
Then you can jion properly. Everything else would require dynamic iterative selection which is not built in to mysql and needs to be done with an external program or by hand.
You can write a script to dynamicall generate a table for each parenttype and childtype though.
Into a very high selective MySQL query, is there a way to know which condition did not match?
Eg.: If I'm looking for 12 conditions and my MySQL returns 0, wich one of these 12 conditions did not match?
SELECT
article.id,
article.name,
GROUP_CONCAT(tags.name order by tags.name) AS nameTags,
GROUP_CONCAT(tags.id order by tags.id) AS idTags,
MAX(IF(article.name LIKE '%var1%',1,0)) AS var1match,
MAX(IF(article.name LIKE '%var2%',1,0)) AS var2match,
and more 10 conditions.
FROM
article
LEFT JOIN ....
LEFT JOIN ....
GROUP BY id
HAVING
(nameTags LIKE '%var1%' OR var1match=1)
AND (nameTags LIKE '%var2%' OR var2match=1)
AND more 10 conditions.
I mean, do it without make 12 single consults to see which one results nothing.
Update: Got some evolution
If I do this:
SELECT
article.id,
MAX(IF(article.name LIKE '%var1%',1,0) AS var1,
MAX(IF(article.name LIKE '%var2%',1,0) AS var2,
MAX(IF(article.name LIKE '%var3%',1,0) AS var3,
FROM
article
LEFT JOIN ....
LEFT JOIN ....
GROUP BY article.id
I'll get an aliased table like this
|id|var1|var2|var3|
| 1| 0| 0| 1|
| 2| 0| 1| 0|
| 3| 0| 0| 0|
| 4| 0| 1| 1|
So I know that 'var 1' doesn't match with the condition because all column value is equal 0. How I get the return of that column name?
Tried to sum value and get columns that sum = 0. Don't know how to do.
Update:
Found to do that is using temporary tables.
1) Create tmp table:
CREATE TEMPORARY TABLE tmp_tagReport AS
SELECT
article.id,
MAX(IF(article.name LIKE '%var1%',1,0) AS l_var1,
MAX(IF(article.name LIKE '%var2%',1,0) AS l_var2,
MAX(IF(article.name LIKE '%var3%',1,0) AS l_var3,
FROM
article
LEFT JOIN ....
LEFT JOIN ....
GROUP BY article.id
You'll have something like this:
|id|l_var1|l_var2|l_var3|
| 1| 0| 0| 1|
| 2| 0| 1| 0|
| 3| 0| 0| 0|
| 4| 0| 1| 1|
2) Sum values and you will know that column with 0 has no match
SELECT
SUM(l_var1) as l_var1,
SUM(l_var2) as l_var2,
SUM(l_var3) as l_var3
You'll get something like this:
|l_var1|l_var2|l_var3|
| 0| 2| 2|
3) Get name of columns with value = 0 in PHP
$querySelect = "SELECT
SUM(l_var1) as l_var1,
SUM(l_var2) as l_var2,
SUM(l_var3) as l_var3
";
$result = mysql_query($querySelect);
$arrayUnfound = array_keys(#mysql_fetch_assoc($result), "0");
print_r($arrayUnfound)
4) It is a temporary table, but I added a drop table just to make sure and try to free memory:
mysql_query("DROP TABLE tmp_tagReport; ");
I found myself a way to do it, but it still has to make 2 or more queries. However I hope it could be helpful.
sorry my english
Thanks
Imagine a dance party where we line up boys on one side and girls on the other. Each boy is placed into table A, once and only once. Likewise for the girls in table B.
We then want to match up the boys in A once and only once with a girl in B, and likewise the girls in B need to match with one and only one boy in A.
A would have an ID column as a primary key and a b_id that would hold the ID of the girl they were matched with, or NULL if not yet matched.
B would have the same for the girls.
Tables would look like this:
table A (boys)
---------
|id|b_id|
---------
| 1|NULL|
| 2|NULL|
| 3|NULL|
| 4|NULL|
| 5|NULL|
| 6|NULL|
---------
table B (girls)
---------
|id|a_id|
---------
| 1|NULL|
| 2|NULL|
| 3|NULL|
| 4|NULL|
| 5|NULL|
| 6|NULL|
---------
What type of query would match one and only one boy with one and only one girl that is not yet matched? Results would look something like this:
results
-------------------------
|a.id|a.b_id|b.id|b.a_id|
-------------------------
| 1| NULL | 1| NULL |
| 2| NULL | 2| NULL |
| 3| NULL | 3| NULL |
| 4| NULL | 4| NULL |
| 5| NULL | 5| NULL |
| 6| NULL | 6| NULL |
-------------------------
I can get these results by using a temp table with unique indexes, but I'm looking for a query to give me the results without a temp table as the real application of this query is going against millions of rows on both sides.
SELECT boyUnmatched.id AS aid
, NULL AS b_id --- you really don't need these two
, girlUnmatched.id AS bid
, NULL AS a_id --- columns, do you?
FROM
( SELECT #rownuma := #rownuma+1 AS rank
, id
FROM a
, (SELECT #rownuma :=0) AS dummy
WHERE b_id IS NULL
ORDER BY id
) AS boyUnmatched
JOIN
( SELECT #rownumb := #rownumb+1 AS rank
, id
FROM b
, (SELECT #rownumb :=0) AS dummy
WHERE a_id IS NULL
ORDER BY id
) AS girlUnmatched
ON boyUnmatched.rank = girlUnmatched.rank