How to Search parent content from multiple table? - mysql

Table - parents
+----+----------+--------------+----------+
| id | user_id | content_type | name |
+----+----------+--------------+----------+
| 1 | 10 | 1 | name - 1 |
| 2 | 12 | 2 | name - 2 |
+----+----------+--------------+----------+
content_type can be
1 = Single part(movies)
2 = Multi prt(serials, episode)
Table - childs
+----+------------+--------------+--------------+-----------+
| id | parent_id | is_episode | episode_name | file_name |
+----+------------+--------------+--------------+-----------+
| 1 | 1 | 0 | NULL | movie.mp4 |
| 2 | 2 | 0 | NULL | zee.mp4 |
| 3 | 2 | 1 | cname-2 | lil-1.mp4 |
| 4 | 2 | 1 | child-2 | lil-2.mp4 |
+----+------------+--------------+--------------+-----------+
And is_episode can be:
0 = No
1 = Yes
NB: some other fields I have skipped
My QUERY:
SELECT F.id,F.user_id,F.content_type,F.name,M.is_episode, M.episode_name, M.file_name
FROM childs M,parents F
WHERE M.parent_id = F.id AND M.is_episode=0 AND
(F.name LIKE '%child%' OR M.episode_name LIKE '%child%' )
Abve MySQL query I am getting 0 record. There is 1 content
My search string applied based on parents.name or childs.episode_name I want to get all record which are is_episode=0 If I search child-2 then findout parent content of my current record. Here is my output should come
+----+----------+----------------+----------+------------+--------------+-----------+
| id | user_id | content_type | name | is_episode | episode_name | file_name |
+----+----------+----------------+----------+------------+--------------+-----------+
| 2 | 12 | 2 | name - 2 | 0 | NULL | zee.mp4 |
+----+----------+----------------+----------+------------+--------------+-----------+
OUTPUTS:
In above my two tables my output should come following criterias
If I search by name LIKE '%name%' output should be
+----+----------+----------------+----------+------------+--------------+
| id | user_id | content_type | name | is_episode | episode_name |
+----+----------+----------------+----------+------------+--------------+
| 1 | 10 | 1 | name - 1 | 0 | NULL |
| 2 | 12 | 2 | name - 2 | 0 | NULL |
+----+----------+----------------+----------+------------+--------------+
If I search by name LIKE '%cname%' or name LIKE '%name - 2%' or name LIKE '%child%' output should be
+----+----------+----------------+----------+------------+--------------+
| id | user_id | content_type | name | is_episode | episode_name |
+----+----------+----------------+----------+------------+--------------+
| 2 | 12 | 2 | name - 2 | 0 | NULL |
+----+----------+----------------+----------+------------+--------------+
If I search by name LIKE '%name - 1%' output should be
+----+----------+----------------+----------+------------+--------------+
| id | user_id | content_type | name | is_episode | episode_name |
+----+----------+----------------+----------+------------+--------------+
| 1 | 10 | 1 | name - 1 | 0 | NULL |
+----+----------+----------------+----------+------------+--------------+
If I search by name LIKE '%child%' output should be
+----+----------+----------------+----------+------------+--------------+
| id | user_id | content_type | name | is_episode | episode_name |
+----+----------+----------------+----------+------------+--------------+
| 2 | 12 | 2 | name - 2 | 0 | NULL |
+----+----------+----------------+----------+------------+--------------+
I am unable to get proper output of my query. Could you plese write down query which is satisfied my all the output.

Your problem is that you're filtering out only rows that has Is_episode = 0 however you need to search in the rows that has is_episode = 1 like cname-2 and child-2
your problem caused because is_episode = 0, remove it and it should work. please leave a comment if you still have a problem.
Update: based in your comments, based on my understanding I think you may require some sort of multiple queries and separation based on the table or your logic/conditions then union results together.
select .. from parent, child .. where is_episode = 0 and name like ...
union
select .. from child join parent where episode_name like ...

Related

How can I get a purchase check in MySQL

I am not able to figure out how I can get the following result with one MySQL Query:
I have two tables:
shop_items
| id | description | price | active |
+----+-------------+-------+--------+
| 1 | product_1 | 5 | 1 |
+----+-------------+-------+--------+
| 2 | product_2 | 10 | 1 |
+----+-------------+-------+--------+
| 3 | product_3 | 15 | 0 |
+----+-------------+-------+--------+
inventory_items (the shop_items a user purchased)
| id | item_id | user_id | active |
+----+---------+---------+--------+
| 1 | 2 | 1 | 1 |
+----+---------+---------+--------+
| 2 | 1 | 1 | 0 |
+----+---------+---------+--------+
I want to see all shop_items where active = 1 including a row called purchased = 0 or 1 based on inventory_items -> matching user_id (where user_id = something) and active = 1
Example output based on the data from above tables -> where user_id = 1:
| item_id | price | description | purchased |
+---------+-------+-------------+-----------+
| 1 | 5 | product_1 | 0 |
+---------+-------+-------------+-----------+
| 2 | 10 | product_2 | 1 |
+---------+-------+-------------+-----------+
What query do I need for this output?
Please note: I only need the result from ONE user_id which I can change within the query :)
Test
SELECT shop_items.*, COALESCE(inventory_items.active, 0) purchased
FROM shop_items
LEFT JOIN inventory_items ON shop_items.id = inventory_items.item_id
AND user_id = 1
WHERE shop_items.active = 1

mysql - dynamic select row as column

Update: I want to use dynamic sql to select question as column and put answer in row, like cursor or loop, is that possible?
I want the select result like this
+--------+---------------+--------------------------------------------------------------------------+
| userid | Living Status | This is another question get from row and it's longer than 64 characters |
+--------+---------------+--------------------------------------------------------------------------+
| 19 | married | q2_opt3 |
+--------+---------------+--------------------------------------------------------------------------+
And here is my query
select
userid,
min(if(question.ordering=1,o.name,NULL )) as 'Living Status',
min(if(question.ordering=2,o.name,NULL )) as 'This is another question get from row and it's longer than 64 characters'
from answer
inner join question on question.key_value = answer.key_value
inner join q_option o on question.id = o.question_id and o.value = answer.answer
where userid in (19)
GROUP BY id
The question table is like
+----+----------+---------------------------------------------------------------------------+--------------+
| id | ordering | question | key_value |
+----+----------+---------------------------------------------------------------------------+--------------+
| 1 | 1 | Living Status | livingStatus |
| 2 | 2 | This is another question get from row and it's longer than 64 characters | question_2 |
+----+----------+---------------------------------------------------------------------------+--------------+
The answer table is like
+----+--------+--------------+--------+
| id | answer | key_value | userid |
+----+--------+--------------+--------+
| 1 | 2 | livingStatus | 19 |
| 2 | 3 | question_2 | 19 |
+----+--------+--------------+--------+
The q_option table is like
+----+----------+-------------+-------+
| id | name | question_id | value |
+----+----------+-------------+-------+
| 1 | single | 1 | 1 |
| 2 | married | 1 | 2 |
| 3 | divorced | 1 | 3 |
| 4 | q2_opt1 | 2 | 1 |
| 5 | q2_opt2 | 2 | 2 |
| 6 | q2_opt3 | 2 | 3 |
+----+----------+-------------+-------+

Proper Indexing MySQL Table

I can't seem to get this query to perform any faster than 8 hours! 0_0
I have read up on indexing and I am still not sure I am doing this right.
I am expecting my query to calculate a value for BROK_1_RATING based on dates and other row values - 500,000 records.
Using record #1 as an example - my query should:
get all other records that have the same ESTIMID
ignore records where ANALYST =""
ignore records where ID is the same as record being compared i.e.
ID != 1
the records must fall within a time frame
i.e. BB.ANNDATS_CONVERTED <= working.ANNDATS_CONVERTED,
BB.REVDATS_CONVERTED > working.ANNDATS_CONVERTED
BB.IRECCD must = 1
Then count the result
Then write the count value to the BROK_1_RATING column for record #1
now do same for record#2, and #3 and so on for the entire table
In human terms - "Examine the date of record #1 - Now, within time frame from record #1 - count the number of times the number 1 exists with the same brokerage ESTIMID, do not count record #1, do not count blank ANALYST rows. Move on to record #2 and do the same"
UPDATE `working` SET `BROK_1_RATING` =
(SELECT COUNT(`ID`) FROM (SELECT `ID`, `IRECCD`, `ANALYST`, `ESTIMID`, `ANNDATS_CONVERTED`, `REVDATS_CONVERTED` FROM `working`) AS BB
WHERE
BB.`ANNDATS_CONVERTED` <= `working`.`ANNDATS_CONVERTED`
AND
BB.`REVDATS_CONVERTED` > `working`.`ANNDATS_CONVERTED`
AND
BB.`ID` != `working`.`ID`
AND
BB.`ESTIMID` = `working`.`ESTIMID`
AND
BB.`ANALYST` != ''
AND
BB.`IRECCD` = 1
)
WHERE `working`.`ANALYST` != '';
| ID | ANALYST | ESTIMID | IRECCD | ANNDATS_CONVERTED | REVDATS_CONVERTED | BROK_1_RATING | NO_TOP_RATING |
------------------------------------------------------------------------------------------------------------------
| 1 | DAVE | Brokerage000 | 4 | 1998-07-01 | 1998-07-04 | | 3 |
| 2 | DAVE | Brokerage000 | 1 | 1998-06-28 | 1998-07-10 | | 4 |
| 3 | DAVE | Brokerage000 | 5 | 1998-07-02 | 1998-07-08 | | 2 |
| 4 | DAVE | Brokerage000 | 1 | 1998-07-04 | 1998-12-04 | | 3 |
| 5 | SAM | Brokerage000 | 1 | 1998-06-14 | 1998-06-30 | | 4 |
| 6 | SAM | Brokerage000 | 1 | 1998-06-28 | 1999-08-08 | | 4 |
| 7 | | Brokerage000 | 1 | 1998-06-28 | 1999-08-08 | | 5 |
| 8 | DAVE | Brokerage111 | 2 | 1998-06-28 | 1999-08-08 | | 3 |
'EXPLAIN' results:
id| select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
----------------------------------------------------------------------------------------------------------------------------------------
1 | PRIMARY | working | index | ANALYST | PRIMARY | 4 | NULL | 467847 | Using where
2 | DEPENDENT SUBQUERY | <derived3> | ALL | NULL | NULL | NULL | NULL | 467847 | Using where
3 | DERIVED | working | index | NULL | test_combined_indexes | 226 | NULL | 467847 | Using index
I have indexes on the single columns - and as well - have tried multiple column index like this:
ALTER TABLE `working` ADD INDEX `test_combined_indexes` (`IRECCD`, `ID`, `ANALYST`, `ESTIMID`, `ANNDATS_CONVERTED`, `REVDATS_CONVERTED`) COMMENT '';
Well you can shorten the query a lot by just removing the extra stuff:
UPDATE `working` as AA SET `BROK_1_RATING` =
(SELECT COUNT(`ID`) FROM `working` AS BB
WHERE BB.`ANNDATS_CONVERTED` <= AA.`ANNDATS_CONVERTED`
AND BB.`REVDATS_CONVERTED` > AA.`ANNDATS_CONVERTED`
AND BB.`ID` != AA.`ID`
AND BB.`ESTIMID` = AA.`ESTIMID`
AND BB.`ANALYST` != ''
AND BB.`IRECCD` = 1 )
WHERE `ANALYST` != '';

Subtract values from line above the current line in MySQL

I've the following table:
| id | Name | Date of Birth | Date of Death | Result |
| 1 | John | 3546565 | 3548987 | |
| 2 | Mary | 5233654 | 5265458 | |
| 3 | Lewis| 6546876 | 6548752 | |
| 4 | Mark | 6546546 | 6767767 | |
| 5 | Steve| 6546877 | 6548798 | |
And I need to do this for the whole table:
Result = 1, if( current_row(Date of Birth) - row_above_current_row(Date of Death))>X else 0
To make things easier, I guess, I created the same table above but with 2 extra id fields: id_minus_one and id_plus_one
Like this:
| id | id_minus_one | id_plus_one |Name | Date_of_Birth | Date_of_Death | Result |
| 1 | 0 | 2 |John | 3546565 | 3548987 | |
| 2 | 1 | 3 |Mary | 5233654 | 5265458 | |
| 3 | 2 | 4 |Lewis| 6546876 | 6548752 | |
| 4 | 3 | 5 |Mark | 6546546 | 6767767 | |
| 5 | 4 | 6 |Steve| 6546877 | 6548798 | |
So my approach would be something like (in pseudo code):
for id=1, ignore result. (Because there is no row above)
for id=2, Result = 1 if( (Where id=2).Date_of_Birth - (where id_minus_one=id-1).Date_of_Death )>X else 0
for id=3, Result = 1 if( (Where id=3).Date_of_Birth - (where id_minus_one=id-1).Date_of_Death)>X else 0
and so on for the whole table...
Just ignore id_plus_one if there is no need for it, I'll use it later for the same thing. So, if I manage to do this for id_minus_one I'll manage for id_plus_one as they are the same algorithm.
My question is how to pass that pseudo code into SQL code, I can't find a way to relate both ids in just one select.
Thank you!
As you describe this, it is just a self join with some logic on the select:
select t.*,
((t.date_of_birth - tprev.date_of_death) > x) as flag
from t left outer join
t tprev
on t.id_minus_one = tprev.id

Fixing Joined Many-to-Many MySQL Query

I have two tables that look like this:
Table A:
+-----+-----+------+-------+
| aID | uID | attr | value |
+-----+-----+------+-------+
| 1 | 1 | fn | john |
+-----+-----+------+-------+
| 2 | 1 | ln | smith |
+-----+-----+------+-------+
| 3 | 2 | fn | jim |
+-----+-----+------+-------+
| 4 | 2 | ln | bean |
+-----+-----+------+-------+
Table B:
+-----+-----+-------+-------+
| bID | uID | perm | value |
+-----+-----+-------+-------+
| 1 | 1 | admin | 1 |
+-----+-----+-------+-------+
| 2 | 2 | news | 1 |
+-----+-----+-------+-------+
| 3 | 2 | cms | 1 |
+-----+-----+-------+-------+
As it shows, Table A holds attribute data for a user uID, and Table B holds permission data for a user uID.
At the moment, I am using,:
SELECT GROUP_CONCAT(`a`.`attr`) AS `attrs`
, GROUP_CONCAT(`a`.`value`) AS `values`
, GROUP_CONCAT(`b`.`perm`) AS `perms`
FROM `a`
JOIN `b`
ON `a`.`uID` = `b`.`uID`
GROUP BY `a`.`uID`, `b`.`uID`
But it is giving me a result:
+-------------+-------------------+-------------------+
| attrs | values | perms |
+-------------+-------------------+-------------------+
| fn,ln | John,Smith | admin,admin |
+-------------+-------------------+-------------------+
| fn,fn,ln,ln | Jim,Jim,Bean,Bean | news,cms,news,cms |
+-------------+-------------------+-------------------+
What do I need to change in my query to get:
+-------+------------+----------+
| attrs | values | perms |
+-------+------------+----------+
| fn,ln | John,Smith | admin |
+-------+------------+----------+
| fn,fn | Jim,Bean | news,cms |
+-------+------------+----------+
GROUP_CONCAT takes additional arguments, as explained on its documentation page here.
The one you want is distinct:
SELECT GROUP_CONCAT(distinct `a`.`attr`) AS `attrs` . . .