MySQL: OUTER JOIN and COUNT() - php
I have table 'posters', table 'reviews' and table 'trailers'. Every table is connected with an movieID column, but each table can be empty for certain movieIDs:
++ posters_table +++ ++ reviews_table ++ ++ trailers_table ++
--itemID--+--filename- --itemID--+--review-- --itemID--+--trailer
---------------------- --------------------- ---------------------
----001---+--0012343-- ----004---+--blalba-- ----002---+--002345--
----001---+--0013331-- ----004---+--xlalxa-- ----005---+--005434--
----002---+--0020052-- ----005---+--zlalza-- ----001---+--005335--
I want to COUNT() the number of posters, reviews and trailers for the specified movieID and get 0 if no available.
So if I want to count movieID = 001 I get: ['posters'] = 2 / ['reviews'] = 0 and ['trailers'] = 1 (for example)
Can someone post the SQL query to do this?
select
(select count(*) from posters_table where itemId = ?) as posters,
(select count(*) from reviews_table where itemId = ?) as reviews,
(select count(*) from trailers_table where itemId = ?) as trailers;
I think if you JOIN the movie table to a result set that gives the count, you can then pick out whether or not the count is > 0 and give the appropriate value:
SELECT movieID, IF(posters.posters_count > 0, posters.posters_count,0) AS posters_total, IF(reviews.reviews_count > 0, reviews.reviews_count,0) AS reviews_total, IF(trailers.trailers_count > 0, trailers.trailers_count,0) AS trailers_total
FROM movies m
LEFT JOIN (SELECT itemID,COUNT(*) AS posters_count FROM posters_table WHERE itemID = '001' GROUP BY itemID) posters ON posters.itemID = movies.movieID
LEFT JOIN (SELECT itemID,COUNT(*) AS reviews_count FROM reviews_table WHERE itemID = '001' GROUP BY itemID) reviews ON reviews.itemID = movies.movieID
LEFT JOIN (SELECT itemID,COUNT(*) AS trailers_count FROM trailers_table WHERE itemID = '001' GROUP BY itemID) trailers ON trailers.itemID = movies.movieID
WHERE m.movieID = '001'
EDIT: I prefers ar's solution. Much simpler!
select
(select count(P.movieid) from posters P where P.movieid=1),
(select count(R.movieid) from reviews R where R.movieid=1),
(select count(T.movieid) from trailers T where T.movieid=1)
The tables are not "really" joined so you need three selects.
Related
Count number of rows for specific ID
In first table album has id and second table album_details has sub_id which relates from album table id I need to display count for separate id value. SELECT DISTINCT B.SUB_ID, A . * , B.CONTENT_VALUE AS detail, (SELECT COUNT( ID ) FROM album_details WHERE A.ID = B.SUB_ID ) AS count FROM album AS A, album_details AS B WHERE A.WEBSITE_ID = '571710720' AND A.ID = B.SUB_ID GROUP BY B.SUB_ID LIMIT 0 , 30 Now count column shows 40 for all rows but need to display 'count' 6 for 'id=4', 'count' 3 for 'id=2'
SELECT count(SUB_ID),SUB_ID from album_details group by SUB_ID
GROUP BY is your weapon of choice. SELECT a.ID, a.CONTENT_VALUE, COUNT(ad.ID) FROM albums AS a LEFT JOIN album_details AS ad ON a.ID = ad.SUB_ID GROUP BY a.ID Feel free to add your WHERE before the GROUP BY.
Lets say first table is A and second table is B then query will be like this select a.ID, count(b.SUB_ID) AS total FROM A LEFT JOIN B ON A.ID = B.SUB_ID Group by B.SUB_ID. It might help you. If not then ask please.
select count(sub_id) as count1 from album_details where sub_id in(select id from album) WHERE album.WEBSITE_ID = '571710720' AND album.ID = album_details.SUB_ID
How to get count of records which have duplicate value in mysql
I have a table with player and status, this table not got corrupted and it has duplicate entries like this: player_id status ---------------------- 1 100 2 100 2 101 3 100 1 101 2 101 As you can see this record is duplicate: 2,101 How can I find such records using a mysql query? I tried: select * from player group by player_id, status having count(status) > 1 but it did not help.
You can SELECT duplicate records as like that: SELECT COUNT(*) as total,player_id,`status` FROM `player` GROUP BY player_id,`status` HAVING total > 1;
Do it in a outer query like select * from ( select *, count(*) as rowcount from player group by player_id, status ) tab where rowcount > 1
You can try this query. $qrys = <<<QUERY select s.id, t.* from player s join ( select player_id, status, count(*) as qty from player group by player_id, status having count(*) > 1 ) t on s.player_id = t.player_id and s.status = t.status QUERY; If you want to delete duplicate record then use this script $delres= mysql_query($qrys); $player_id = 0; $status = 0; while ($r= mysql_fetch_array($delres)){ if($player_id == $r['player_id'] && $status == $r['status']) mysql_query("DELETE FROM player WHERE id=".$r['id']); $player_id = $r['player_id']; $status = $r['status']; }
Try this : select * from player p inner join ( select player_id, count(*) as duplicate from player group by player_id having count(*) > 1) pp on p.player_id = pp.player_id
Try This SELECT *, COUNT(status) AS rows_count FROM player GROUP BY player_id, status HAVING COUNT(status) > 0
You query is near to it just some changes in it to give you count column for every options Try this modified query. select *, count(status) as count from player group by player_id, status having count(status) > 0 It will give this type of response
you can do that by SELECT distinct player .* FROM player as tb1 join player as tb2 WHERE tb1.status = tb2.status and tb1.player_id < tb2.player_id
You can do it simply with GROUP BY like this SELECT `player_id`, `status`, COUNT(*) as cnt FROM `player` GROUP BY CONCAT(`player_id`, '_', `status`) HAVING cnt > 1 result would be player_id status cnt 2 101 2
Limiting a left join to returning one result?
I currently have this left join as part of a query: LEFT JOIN movies t3 ON t1.movie_id = t3.movie_id AND t3.popularity = 0 The trouble is that if there are several movies with the same name and same popularity (don't ask, it just is that way :-) ) then duplicate results are returned. All that to say, I would like to limit the result of the left join to one. I tried this: LEFT JOIN (SELECT t3.movie_name FROM movies t3 WHERE t3.popularity = 0 LIMIT 1) ON t1.movie_id = t3.movie_id AND t3.popularity = 0 The second query dies with the error: Every derived table must have its own alias I know what I'm asking is slightly vague since I'm not providing the full query, but is what I'm asking generally possible?
The error is clear -- you just need to create an alias for the subquery following its closing ) and use it in your ON clause since every table, derived or real, must have its own identifier. Then, you'll need to include movie_id in the subquery's select list to be able to join on it. Since the subquery already includes WHERE popularity = 0, you don't need to include it in the join's ON clause. LEFT JOIN ( SELECT movie_id, movie_name FROM movies WHERE popularity = 0 ORDER BY movie_name LIMIT 1 ) the_alias ON t1.movie_id = the_alias.movie_id If you are using one of these columns in the outer SELECT, reference it via the_alias.movie_name for example. Update after understanding the requirement better: To get one per group to join against, you can use an aggregate MAX() or MIN() on the movie_id and group it in the subquery. No subquery LIMIT is then necessary -- you'll receive the first movie_id per name withMIN() or the last with MAX(). LEFT JOIN ( SELECT movie_name, MIN(movie_id) AS movie_id FROM movies WHERE popularity = 0 GROUP BY movie_name ) the_alias ON t1.movie_id = the_alias.movie_id
LEFT JOIN movies as m ON m.id = ( SELECT id FROM movies mm WHERE mm.movie_id = t1.movie_id ORDER BY mm.id DESC LIMIT 1 )
you could try to add GROUP BY t3.movie_id to the first query
Try this: LEFT JOIN ( SELECT t3.movie_name, t3.popularity FROM movies t3 WHERE t3.popularity = 0 LIMIT 1 ) XX ON t1.movie_id = XX.movie_id AND XX.popularity = 0
On MySQL 5.7+ use ANY_VALUE & GROUP_BY: SELECT t1.id,t1.movie_name, ANY_VALUE(t3.popularity) popularity FROM t1 LEFT JOIN t3 ON (t3.movie_id=t1.movie_id AND t3.popularity=0) GROUP BY t1.id more info LEFT JOIN only first row https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
Easy solution to left join the 1 most/least recent row is using select over ON phrase SELECT A.ID, A.Name, B.Content FROM A LEFT JOIN B ON A.id = (SELECT MAX(id) FROM B WHERE id = A.id) Where A.id is the auto-incremental primary key.
LEFT JOIN ( SELECT id,movie_name FROM movies GROUP BY id ) as m ON ( m.id = x.id )
// Mysql SELECT SUM(db.item_sales_nsv) as total FROM app_product_hqsales_otc as db LEFT JOIN app_item_target_otc as it ON db.id = (SELECT MAX(id) FROM app_item_target_otc as ot WHERE id = db.id) and db.head_quarter = it.hqcode AND db.aaina_item_code = it.aaina_item_code AND db.month = it.month AND db.year = it.year WHERE db.head_quarter = 'WIN001' AND db.month = '5' AND db.year = '2022' AND db.status = '1'
Slow query with IN operator
I am having a problem with one query. I am sure that the problem is IN operator but I don't know how and with what should I replace it? Query: SELECT `a`.`title`, `a`.`askprice`, `a`.`picture`, `a`.`description`, `a`.`userid`, `a`.`id` FROM (`mm_ads` AS a) LEFT JOIN `mm_ads_fields_values` AS afv ON `a`.`id` = `afv`.`aid` WHERE `a`.`status` = 1 AND `a`.`category` = '230' AND `a`.`id` IN (2194,2200,2205,2215,2233,2238,2240,0,2243,2255,2257,2260,2263,2264,2266,2269,2272,2274,2276,2277,2279,2282,2284,2286,2288,2293,2297,2300,2303,2306,2310,2311,2318,2322,2324,2326,2330,2335,2340,2347,2351,2357,2364,2370,2375,2387,2391,2399,2404,2408,2413,2571,2574,2576,2578,2580,2582,2584,2586,2588,2590,2592,2597,2599,2601,2605,2606,2612,2615,2618,2621,2626,2628,2632,2637,2639,2641,2643,2646,2647,2653,2662,2664,2667,2670,2673,2677,2680,2687,2689,2691,2693,2696,2698,2701,2703,2705,2708,2710,2711,3666,3674,3693,3697,3704,3711,3718,3727,3732,3736,3761,3764,3771,3776,3779,3786,3802,3807,3813,3818,3844,3847,3853,3866,3870,3873,3879,3883,4283,4287,4292,4300,4305,4313,4332,4339,4348,4354,4361,4367,4371,4378,4391,4412,4424,4441,4445,4451,4458,4466,4473,4479,4494,4508,4515,4523,4530,4537,4541,4542,4575,4584,4602,4621,4629,4638,4647,4652,4659,4665,4670,4677,4684,4690,4693,4702,4712,4720,4726,4732,4740,4747,4755,4763,4772,4776,4779,4784,4788,4790,4793,4797,4802,4807,4811,4818,4824,4831,4839,4844,4848,4851,4855,4867,4873,4877,4887,4894,4897,4901,4908,4912,4916,4926,4932,4939,4944,4949,4956,4959,4968,4977,4981,5001,5008,5012,5015,5021,5027,5034,5038,5045,5048,5053,5058,5063,5066,5070,5071,5077,5080,5085,5089,5096,5104,5108,5113,5114,5120,5127,5131,5135,5141,5150,5155,5159,5170,5174,5179,5187,5196,5205,5209,5215,5236,5254,5273,5281,5290,5309,5319,5323,5327,5350,5357,5363,5364,5372,5378,5409,5425,5434,5442,5461,5468,5477,5489,5497,5501,5515,5522,5529,5536,5541,5548,5558,5569,5585,5591,5597,5611,5619,5626,5635,5644,5653,5661,5667,5680,5688,5695,5702,5713,5725,5730,5734,5766,5781,5830,5882,5896,5928,5936,5943,5952,5958,5973,5998,6007,6018,6026,6083,6097,6103,6109,6114,6119,6124,6130,6136,6144,6152,6158,6172,6181,6192,6202,6211,6218,6223,6226,6230,6234,6239,6246,6256,6259,6266,6269,6273,6277,6282,6286,6291,6297,6301,6305,6309,6312,6315,6321,6326,6333,6338,6347,6352,6358,6365,6367,6372,6383,6389,6396,6401,6408,6413,6420,6424,6433,6471,6477,6487,6493,6498,6502,6506,6509,6511,6514,6519,6532,6539,6546,6551,6557,6562,6568,6577,6611,6618,6622,6625,6630,6635,6639,6648,6650,6653,6657,6661,6664,6671,6672,6679,6683,6687,6692,6695,6700,6704,6709,6712,6713,6716,6719,6724,6725,6733,6736,6754,6776,6781,6784,6791,6794,6807,6811,6816,6821,6826,6827,6867,6873,6879,6883,6893,6900,6908,6913,6919,6925,6931,6935,6944,6950,6955,6959,6964,6967,6970,6986,6990,6995,6998,7001,7003,7007,7012,7015,7019,7023,7025,7030,7033,7037,7041,7046,7052,7053,7057,7060,7063,7065,7068,7081,7085,7090,7091,7094,7096,7101,7107,7113,7116,7119,7122,7130,7138,7153,7154,7158,7161,7164,7167,7177,7179,7190,7198,7203,7207,7211,7215,7225,7229,7235,7240,7242,7248,7253,7256,7258,7259,7263,7269,7275,7277,7282,7285,7290,7294,7298,7302,7306,7310,7316,7318,7321,7326,7331,7336,7339,7345,7348,7355,7359,7364,7369,7374,7379,7383,7386,7391,7395,7399,7403,7410,7415,7418,7423,7427,7432,7434,7438,7457,7458,7460,7463,7465,7468,7471,7474,7476,7479,7481,7483,7485,7487,7490,7492,7494,7498,7501,7504,7507,7511,7514,7517,7520,7525,7530,7534,7540,7543,7546,7548,7551,7591,7596,7599,7606,7609,7615,7622,7629,7639,7643,7648,7650,7658,7662,7667,7670,7677,7681,7686,7691,7693,7700,7702,7707,7712,7716,7725,7740,7746,7752,7759,7760,7763,7766,7772,7776,7985,7993,8000,8007,8028,8035,8042,8050,8057,8067,8074,8084,8091,8097,8103,8109,8111,8129,8233,8237,8241,8245,8249,8252,8260,8264,8292,8300,8309,8397,8420,8426,8430,8434,8437,8444,8448,8454,8462,8470,8477,8483,8488,8492,8499,8509,8515,8520,8526,8531,8538,8543,8548,8552,8557,8561,8565,8569,8573,8576,8581,8586,8594,8599,8608,8612,8615,8620,8624,8629,8632,8638,8641,8646,8650,8654,8655,8660,8665,8668,8673,8675,8681,8686,8691,8695,8700,8704,8708,8713,8718,8722,8727,8742,8747,8780,8783,8786,8789,8793,8797,8802,8807,8810,8813,8816,8819,8821,8825,8828,8831,8834,8839,8844,8847,8852,8853,8855,8858,8861,8864,8868,8872,8874,8878,8880,8884,8888,8891,8897,8902,8907,8916,8917,8921,8925,8929,8934,8939,8946,8959,8960,8966,8972,8979,8982,8987,8992,8994,9008,9011,9014,9018,9023,9027,9031,9035,9040,9043,9046,9053,9057,9061,9066,9071,9075,9078,9081,9086,9090,9095,9102,9105,9112,9117,9121,9129,9132,9137,9140,9142,9145,9151,9156,9171,9176,9192,9196,9202,9207,9213,9219,9222,9225,9229,9235,9242,9250,9263,9269,9273,9278,9284,9295,9303,9304,9305,9311,9319,9322,9328,9332,9335,9339,9346,9350,9355,9361,9366,9370,9375,9379,9382,9385,9392,9397,9400,9404,9410,9413,9418,9421,9424,9437,9441,9446,9451,9457,9466,9477,9481,9492,9495,9511,9516,9519,9523,9526,9532,9543,9684,9690,9387,8911,8228,8116,7756,6887,6829,5966,5335,5315,5300,4400,3840,12881,12893,12898,1180,1499,2188,2251,2256,2295,9462,9529,9750,9922,10087,10107,11089,11392,9605,9607,9612,9615,9619,9627,9633,9638,9640,9642,9669,9677,9681,9694,9697,9703,9707,9709,9711,9714,9716,9720,9726,9730,9733,9737,9740,9745,9752,9757,9767,9776,9778,9779,9784,9787,9789,9792,9796,9799,9803,9806,9811,9818,9820,9826,9827,9832,9836,9845,9847,9850,9852,9855,9858,9861,9862,9864,9868,9871,9875,9882,9886,9889,9892,9897,9899,9903,9907,9913,9916,9920,9926,9928,9930,9932,9936,9940,9943,9946,9950,9954,9957,9962,9964,9966,9973,9976,9977,9980,9981,9985,9986,9987,9989,10019,10022,10025,10027,10028,10055,10062,10189,10195,10197,10212,10220,10221,10224,10226,10229,10231,10232,10235,10428,10431,10434,10438,10440,10442,10443,10445,10448,10449,10455,10459,10466,10469,10471,10473,10474,10475,10476,10478,10481,10484,10486,10489,10493,10494,10496,10497,10499,10501,10502,10503,10508,10511,10514,10516,10518,10521,10524,10528,10529,10532,10160,10158,10156,10153,10149,10146,10138,10133,10132,10129,10126,10123,10119,10117,10116,10112,10111,10109,10101,10099,10097,10093,10090,10086,10084,10082,10078,10074,10070,10066,10045,10052,10041,10037,10036,10033,18596) AND `a`.`userid` = '136' GROUP BY `a`.`id` ORDER BY `id` DESC, `id` DESC LIMIT 15; How can I improve the speed of that query? Let me explain my tables: mm_ads: Table where ads are stored in mm_ads_fields_values: Table where options for ads are stored in. Example: Car is ad and having one row in table mm_ads. Car has following options: brand, model, color,... So Car ad has more than one row in table mm_ads_fields_values. So if I search only cars with "black" color, the query will get first all IDs that have color option set to "black". Then I put these IDs to query. Update: Columns in table mm_ads_fields_values: id, aid, db_name, value Sorry for my bad English..
Remove the LEFT JOIN and GROUP BY parts: SELECT `a`.`title`, `a`.`askprice`, `a`.`picture`, `a`.`description`, `a`.`userid`, `a`.`id` FROM `mm_ads` AS a WHERE `a`.`status` = 1 AND `a`.`category` = '230' AND `a`.`id` IN (…) AND `a`.`userid` = '136' ORDER BY `id` DESC LIMIT 15 Make sure that id is defined as a PRIMARY KEY. I'm assuming the query is built by an ORM so recheck your model definition, the LEFT JOIN and GROUP BY are redundant here. Update: If you are searching for black cars, you can do it in a single query like this: SELECT a.* FROM mm_ads_fields_values afv JOIN mm_ads a ON a.id = afv.aid WHERE afv.field = 'color' AND afv.value = 'black' ORDER BY afv.aid DESC LIMIT 15 Create a composite index on mm_ads_fields_values (field, value, aid). Update 2: To find black BMW: SELECT a.* FROM ( SELECT aid FROM mm_ads_field_values afv WHERE (field, value) = ('color', 'black') OR (field, value) = ('model', 'BMW') GROUP BY aid HAVING COUNT(*) = 2 ORDER BY aid DESC LIMIT 15 ) af JOIN mm_ads a ON a.id = af.aid ORDER BY aid DESC
How to specify the parent query field from within a subquery in MySQL?
How do I specify the parent query field from within a subquery in MySQL? For Example: I have written a basic Bulletin Board type program in PHP. In the database each post contains: id(PK) and parent_id(the id of the parent post). If the post is itself a parent, then its parent_id is set to 0. I am trying to write a mySQL query that will find every parent post and the number of children that the parent has. $query = "SELECT id, ( SELECT COUNT(1) FROM post_table WHERE parent_id = id ) as num_children FROM post_table WHERE parent_id = 0"; The tricky part is that the first id doesn't know that it should be referring to the second id that is outside of the subquery. I know that I can do SELECT id AS id_tmp and then refer to it inside the subquery, but then if I want to also return the id and keep "id" as the column name, then I'd have to do a query that returns me 2 columns with the same data (which seems messy to me) $query = "SELECT id, id AS id_tmp, (SELECT COUNT(1) FROM post_table WHERE parent_id = id_tmp) as num_children FROM post_table WHERE parent_id = 0"; The messy way works fine, but I feel an opportunity to learn something here so I thought I'd post the question.
How about: $query = "SELECT p1.id, (SELECT COUNT(1) FROM post_table p2 WHERE p2.parent_id = p1.id) as num_children FROM post_table p1 WHERE p1.parent_id = 0"; or if you put an alias on the p1.id, you might say: $query = "SELECT p1.id as p1_id, (SELECT COUNT(1) FROM post_table p2 WHERE p2.parent_id = p1.id) as num_children FROM post_table p1 WHERE p1.parent_id = 0";
You could try something like this SELECT pt.id, CountTable.Cnt FROM post_table pt LEFT JOIN ( SELECT parent_id, COUNT(1) Cnt FROM post_table WHERE parent_id <> 0 GROUP BY parent_id ) CountTable ON pt.id = CountTable.parent_id WHERE pt.parent_id = 0 To get back to your example, use the alias of the main table in the sub select SELECT pt.id, (SELECT COUNT(1) FROM post_table WHERE parent_id = pt.id) FROM post_table pt WHERE pt.parent_id = 0
Give the tables unique names: $query = "SELECT a.id, (SELECT COUNT(1) FROM post_table b WHERE parent_id = a.id) as num_children FROM post_table a WHERE a.parent_id = 0";
The following syntax works in Oracle. Can you test if the same works in MYSQL too? It is called scalar subquery in Oracle. You would just need to alias the two tables differently to distinguish between them if you are using the same table twice. sql> select empno, 2 (select dname from dept where deptno = emp.deptno) dname 3 from emp 4 where empno = 7369; EMPNO DNAME ---------- -------------- 7369 RESEARCH sql> select parent.empno, 2 (select mgr from emp where empno = parent.empno) mgr 3 from emp parent 4 where empno = 7876; EMPNO MGR ---------- ---------- 7876 7788
Thanks Don. I had a nested query as shown below and a WHERE clause in it wasn't able to determine alias v1. Here is the code which isn't working: Select teamid, teamname FROM team as t1 INNER JOIN ( SELECT venue_id, venue_scores, venue_name FROM venue WHERE venue_scores = ( SELECT MAX(venue_scores) FROM venue as v2 WHERE v2.venue_id = v1.venue_id /* this where clause wasn't working */ ) as v1 /* v1 alias already present here */ ); So, I just added the alias v1 again inside the JOIN. Which made it work. Select teamid, teamname FROM team as t1 INNER JOIN ( SELECT venue_id, venue_scores, venue_name FROM venue as v1 /* added alias v1 here again */ WHERE venue_scores = ( SELECT MAX(venue_scores) FROM venue as v2 WHERE v2.venue_id = v1.venue_id /* Now this works!! */ ) as v1 /* v1 alias already present here */ ); Hope this will be helpful for someone.
Parent query field within a subquery in MySQL 8. I'm selecing games scores on the basis of username from tblgamescores using nested query. SELECT GameScoresID, (SELECT Username FROM tblaccounts WHERE AccountID = FromAccountID) AS FromUsername, (SELECT Username FROM tblaccounts WHERE AccountID = ToAccountID) AS ToUsername, (SELECT Username FROM tblaccounts WHERE AccountID = WinAccountID) AS WinUsername, (SELECT Username FROM tblaccounts WHERE AccountID = LossAccountID) AS LossUsername, FromUserScore, ToUserScore FROM tblgamescores a WHERE FromAccountID = (SELECT AccountID FROM tblaccounts WHERE Username = "MHamzaRajput");