MYSQL multible inner join too long time - mysql

I built a query with multiple Inner join and it is taking too long time to execute.
I think it's happens because of tables indexes
the query statement is :
SELECT DISTINCT
`result_authors`.`id`,
`result_authors`.`name`,
`result_authors`.`author_id`,
`platforms`.`platform`
FROM
`result_authors`
INNER JOIN
`results` ON `result_authors`.`result_id` = `results`.`id`
INNER JOIN
`queries` ON `queries`.`id` = `results`.`query_id`
INNER JOIN
`wall_queries` ON `wall_queries`.`query_id` = `queries`.`parent_id`
INNER JOIN
`walls` ON `walls`.`id` = `wall_queries`.`wall_id`
INNER JOIN
`platforms` ON `result_authors`.`platform_id` = `platforms`.`id`
WHERE
`walls`.`id` = 2
GROUP BY `result_authors`.`author_id` , `result_authors`.`id` , `result_authors`.`name` , `result_authors`.`profile` , `result_authors`.`platform_id` , `platforms`.`platform`
ORDER BY `result_authors`.`name` ASC;
Query Explain
+------+-------------+----------------------------------------------------------------------------------------------------------------+----------------------------------+-------------+------------------------------------+------+-------------+----------------------------------------------+
| id | select_type | table | id | select_type | table | id | select_type | table |
+------+-------------+----------------------------------------------------------------------------------------------------------------+----------------------------------+-------------+------------------------------------+------+-------------+----------------------------------------------+
| NULL | const | PRIMARY | PRIMARY | 8 | const | 1 | 100 | Using index; Using temporary; Using filesort |
| NULL | ref | wall_queries_query_id_foreign,wall_queries_wall_id_foreign | wall_queries_wall_id_foreign | 8 | const | 1 | 100 | NULL |
| NULL | ref | PRIMARY,queries_parent_id_index | queries_parent_id_index | 8 | db_name.wall_queries.query_id | 1 | 100 | Using where; Using index |
| NULL | ref | PRIMARY,results_query_id_foreign,results_query_id_index | results_query_id_foreign | 9 | db_name.queries.id | 6402 | 100 | NULL |
| NULL | ref | result_authors_platform_id_foreign,result_authors_result_id_foreign,result_authors_result_id_platform_id_index | result_authors_result_id_foreign | 8 | db_name.results.id | 1 | 100 | Using where |
| NULL | eq_ref | PRIMARY | PRIMARY | 4 | db_name.result_authors.platform_id | 1 | 100 | NULL |
+------+-------------+----------------------------------------------------------------------------------------------------------------+----------------------------------+-------------+------------------------------------+------+-------------+----------------------------------------------+
this code taking more than 15 minutes to get 28000 row.
Tables
Table : result_authors
+----+------------+---------------+-----------------------------------+-----------+-------------+---------------------+---------------------+
| id | author_id | name | profile | result_id | platform_id | created_at | updated_at |
+----+------------+---------------+-----------------------------------+-----------+-------------+---------------------+---------------------+
| 1 | 420000242 | Author Name 1 | https://twitter.com/profile_slug1 | 15452 | 2 | 2017-11-24 13:55:41 | 2017-11-24 14:13:13 |
| 2 | 400070242 | Author Name 2 | https://twitter.com/profile_slug2 | 5225 | 2 | 2017-11-24 13:58:03 | 2017-11-24 14:13:13 |
| 3 | 2200059092 | Author Name 3 | https://twitter.com/profile_slug3 | 487 | 2 | 2017-11-24 19:48:55 | 2017-11-24 19:48:55 |
+----+------------+---------------+-----------------------------------+-----------+-------------+---------------------+---------------------+
Table:queries
+----+---------------+---------+-----------+-------------+---------------------+
| id | title | type | parent_id | category_id | updated_at |
+----+---------------+---------+-----------+-------------+---------------------+
| 1 | Query title 1 | public | 1 | 5 | 2017-10-24 13:21:17 |
| 2 | Query title 2 | private | 2 | 1 | 2017-10-31 16:23:09 |
| 3 | Query title 3 | public | 1 | 5 | 2017-10-31 16:20:38 |
+----+---------------+---------+-----------+-------------+---------------------+
Table : walls
+----+--------------+---------------------+
| id | name | updated_at |
+----+--------------+---------------------+
| 10 | Wall title 1 | 2017-11-16 13:42:32 |
| 11 | Wall title 2 | 2017-11-16 15:01:49 |
| 12 | Wall title 3 | 2017-11-19 12:05:18 |
+----+--------------+---------------------+
Table : platforms
+----+-----------+------------------------------+---------------------+---------------------+
| id | platform | module | created_at | updated_at |
+----+-----------+------------------------------+---------------------+---------------------+
| 1 | facebook | \platforms\FacebookPlatform | 2017-09-15 00:54:49 | 2017-09-15 00:54:49 |
| 2 | twitter | \platforms\TwitterPlatform | 2017-09-15 00:54:49 | 2017-09-15 00:54:49 |
| 3 | wordpress | \platforms\WordpressPlatform | 2017-09-15 00:54:49 | 2017-09-15 00:54:49 |
+----+-----------+------------------------------+---------------------+---------------------+
Results looks like
+----+----------+-----------+----------+
| id | name | author_id | platform |
+----+----------+-----------+----------+
| 1 | Author 1 | 123 | twitter |
| 3 | Author 2 | 124 | facebook |
| 8 | Author 3 | 125 | twitter |
+----+----------+-----------+----------+
Any help to improve performance of the sql query?
Note: I'm using laravel query builder.

Related

How to find a specific row in an index [duplicate]

This question already has answers here:
Select all where [first letter starts with B]
(6 answers)
Closed last year.
I am new to MySQL and am not very familiar with it. I am supposed to find a name that starts with b in index, which i do not have the slightest clue of doing.
| id | name | DoB | class | marks | dept_id |
+----+--------------+------------+-------+-------+---------+
| 1 | Data Science | 2006-07-15 | 11 | 100 | 3 |
| 2 | Garry | 2006-08-20 | 11 | 92 | 4 |
| 3 | Jane | 2006-03-22 | 10 | 95 | 2 |
| 4 | Benny | 2005-10-10 | 12 | 74 | 4 |
| 5 | Karen | 2005-01-15 | 12 | 88 | 3 |
| 6 | Camy | 2006-04-18 | 12 | 91 | 2 |
| 7 | Farhan | 2006-09-21 | 11 | 80 | NULL |
| 8 | Shamil | 2005-10-19 | 11 | 90 | 3 |
+----+--------------+------------+-------+-------+---------+
The Table above is (students)
And the one Below it is the Index of (students)
+----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| students | 0 | PRIMARY | 1 | id | A | 6 | NULL | NULL | | BTREE | | | YES | NULL |
| students | 1 | dept_id | 1 | dept_id | A | 3 | NULL | NULL | YES | BTREE | | | YES | NULL |
| students | 1 | name_index | 1 | name | A | 6 | NULL | NULL | | BTREE | | | YES | NULL |
| students | 1 | index_name | 1 | name | A | 6 | NULL | NULL | | BTREE | | | YES | NULL |
+----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
You have to use SELECT query with LIKE keyword
The percentage ( % ) wildcard matches any string of zero or more characters. For example, b% matches any string starts with the character b such as Benny and Ben.
SELECT * FROM students WHERE name LIKE 'b%';
If you have same name in record which starts from uppercase as well as lowecase then put BINARY keyword after LIKE keyword (Case Sensitive):
SELECT * FROM students WHERE name LIKE BINARY 'b%';

mysql create multiple select to put max in all rows

This is my table with sample data:
Table:PersTrans
+------------+-------------+------+-----+------------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+------------+-------+
| PersTrID | char(10) | NO | PRI | | |
| PersTrSeq | int(11) | NO | PRI | 0 | |
| PersTrDate | date | YES | | 1001-01-01 | |
| PersTrPaid | float(9,2) | YES | | 0.00 | |
+------------+-------------+------+-----+------------+-------+
mysql> select * from PersTrans;
+------------+-----------+-----------+-------------+
| PersTrID | PersTrSeq | PersTrDate | PersTrPaid |
+------------+-----------+-----------+-------------+
| MOCK | 1 | 2015-10-10 | 400.00 |
| MOCK | 2 | 2017-11-07 | 10.00 |
| NAGA | 1 | 2015-11-11 | 500.00 |
| NASSA | 1 | 2015-12-16 | 800.00 |
+------------+-----------+-----------+-------------+
I'd like to pick up the maximum PersTrSeq, and attach it to all the records that have the same PersTrId. What I want:
+------------+-----------+------------+------------+----------------+
| PersTrID | PersTrSeq | PersTrDate | PersTrPaid | max(PersTrSeq) |
+------------+-----------+-----------+------------+-----------------+
| MOCK | 1 | 2015-10-10 | 400.00 | 2 |
| MOCK | 2 | 2017-11-07 | 10.00 | 2 |
| NAGA | 1 | 2015-11-11 | 500.00 | 1 |
| NASSA | 1 | 2015-12-16 | 800.00 | 1 |
+------------+-----------+-----------+------------+-----------------+
These two attempts didn't work. I've looked for other suggestions but haven't found anything helpful.
mysql> SELECT *, max(PersTrSeq) from PersTrans where PersTransId = 'Mock' group by PersTrSeq;
+------------+-----------+------------+------------+----------------+
| PersTrID | PersTrSeq | PersTrDate | PersTrPaid | max(PersTrSeq) |
+------------+-----------+-----------+------------+-----------------+
| MOCk | 1 | 2015-10-10 | 400.00 | 1 |
| MOCK | 2 | 2017-11-07 | 10.00 | 2 |
+------------+-----------+-----------+------------+-----------------+
mysql> SELECT *, max(PersTrSeq) as maxseq from PersTrans group by PersTrId;
+------------+-----------+------------+------------+--------+
| PersTrID | PersTrSeq | PersTrDate | PersTrPaid | maxseq |
+------------+------------+-----------+------------+--------+
| MOCK | 1 | 2015-10-10 | 400.00 | 2 |
| NAGA | 1 | 2015-11-11 | 500.00 | 1 |
| NASSA | 1 | 2015-12-16 | 800.00 | 1 |
+------------+-----------+-----------+------------+---------+
Can anyone offer a single query that will get the result I'm looking for?
Following query will work:
select *,
(select max(PersTrSeq) from PersTrans p2
where p2.PersTrId = p1.PersTrId
) as maxSeq
from PersTrans p1;
If I understand what you want, you want the same number of records as the actual data, substituting the max(PersTrSeq) for all rows with a certain PersTrID.
SELECT
`PerTrID`,
(SELECT max(`PersTrSeq`) FROM `PersTrans` b WHERE b.`PersTrID = a.`PersTrID`) as `PersTrSeq`,
`PersTrDate`,
`PersTrPaid`,
from `PersTrans` a

Select Same Column From 2 Tables into 1 Column in View

I have two column with the same name in different tables.
I want to join them into one column in a view.
Here my first table stocks:
+----------+------------+------------+---------+----------------+--------+
| stock_id | stock_cost | stock_left | item_id | purchasedtl_id | trx_id |
+----------+------------+------------+---------+----------------+--------+
| 1 | 1000 | 0 | 1 | 1 | 1 |
| 2 | 1000 | 5 | 1 | 2 | 2 |
| 3 | 1000 | 1 | 1 | 3 | 4 |
+----------+------------+------------+---------+----------------+--------+
Second table stocks_out
+-------------+----------------+--------------+---------+----------+------------+--------+
| stockout_id | stockout_price | stockout_qty | item_id | stock_id | saledtl_id | trx_id |
+-------------+----------------+--------------+---------+----------+------------+--------+
| 1 | 2000 | 1 | 1 | 1 | 1 | 3 |
+-------------+----------------+--------------+---------+----------+------------+--------+
And I want to join them to be like this trx_id, trx_no, trx_closetime, trx_type stock_id, stock_cost, stockout_id, stock_out_cost, stockout_price, item_id
item_id is the field I want to join in one column.
The current Query is :
select `transactions`.`trx_id` AS `trx_id`,`transactions`.`trx_no` AS `trx_no`,`transactions`.`trx_closetime` AS `trx_closetime`,`transactions`.`trx_type` AS `trx_type`,`stocks`.`stock_id` AS `stock_id`,`stocks`.`stock_cost` AS `stock_cost`,`stock_out`.`stockout_id` AS `stockout_id`,`stock_out`.`stockout_price` AS `stockout_price` from ((`transactions` left join `stocks` on(`stocks`.`trx_id` = `transactions`.`trx_id`)) left join `stock_out` on(`stock_out`.`trx_id` = `transactions`.`trx_id`)) order by `transactions`.`trx_closetime`;
And the current result:
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
| trx_id | trx_no | trx_closetime | trx_type | stock_id | stock_cost | stockout_id | stockout_price |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
| 1 | 02002-02-170415-001 | 2017-04-15 19:40:03 | 2 | 1 | 1000 | NULL | NULL |
| 2 | 02002-02-170415-002 | 2017-04-15 19:40:13 | 2 | 2 | 1000 | NULL | NULL |
| 3 | 02002-01-170415-001 | 2017-04-15 19:40:57 | 1 | NULL | NULL | 1 | 2000 |
| 4 | 02002-02-170415-003 | 2017-04-15 19:41:14 | 2 | 3 | 1000 | NULL | NULL |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
Found it guys.
I just need to add the following query as the column
COALESCE(`stocks`.`item_id`, `stocks_out`.`item_id`) AS `item_id`
So the query will be like
select `transactions`.`trx_id` AS `trx_id`,`transactions`.`trx_no` AS `trx_no`,`transactions`.`trx_closetime` AS `trx_closetime`,`transactions`.`trx_type` AS `trx_type`,`stocks`.`stock_id` AS `stock_id`,`stocks`.`stock_cost` AS `stock_cost`,`stock_out`.`stockout_id` AS `stockout_id`,`stock_out`.`stockout_price` AS `stockout_price`, COALESCE(`stocks`.`item_id`, `stocks_out`.`item_id`) AS `item_id from ((`transactions` left join `stocks` on(`stocks`.`trx_id` = `transactions`.`trx_id`)) left join `stock_out` on(`stock_out`.`trx_id` = `transactions`.`trx_id`)) order by `transactions`.`trx_closetime`;
And the result:
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+
| trx_id | trx_no | trx_closetime | trx_type | stock_id | stock_cost | stockout_id | stockout_price | item_id |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+
| 1 | 02002-02-170415-001 | 2017-04-15 19:40:03 | 2 | 1 | 1000 | NULL | NULL | 1 |
| 2 | 02002-02-170415-002 | 2017-04-15 19:40:13 | 2 | 2 | 1000 | NULL | NULL | 1 |
| 3 | 02002-01-170415-001 | 2017-04-15 19:40:57 | 1 | NULL | NULL | 1 | 2000 | 1 |
| 4 | 02002-02-170415-003 | 2017-04-15 19:41:14 | 2 | 3 | 1000 | NULL | NULL | 1 |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+

Mysql exclusive left join on one to many relationship

I have these two tables
facilities
+----+--------------------------------------+--------------+-------+------+------------+------------+
| id | name | category | image | cust | created_at | updated_at |
+----+--------------------------------------+--------------+-------+------+------------+------------+
| 1 | Bar | hotel | | | NULL | NULL |
| 2 | Minibar in alle Zimmer | hotel | | | NULL | NULL |
| 3 | Snack restaurant | hotel | | | NULL | NULL |
| 4 | Grillroom | hotel | | | NULL | NULL |
+----+--------------------------------------+--------------+-------+------+------------+------------+
table - 2
resortfacilities
+----+------+---------------------+---------------------+------+
| id | f_id | created_at | updated_at | h_id |
+----+------+---------------------+---------------------+------+
| 42 | 4 | 2016-09-21 13:17:27 | 2016-09-21 13:17:27 | 35 |
| 59 | 1 | 2016-09-22 10:23:27 | 2016-09-22 10:23:27 | 38 |
| 60 | 4 | NULL | NULL | 38 |
+----+------+---------------------+---------------------+------+
And I have ran this following sql
SELECT
facilities.id,
facilities.`name`,
facilities.image,
resortfacilities.h_id
FROM
facilities
LEFT JOIN resortfacilities ON facilities.id = resortfacilities.f_id
WHERE
resortfacilities.f_id IS NULL AND
facilities.category = 'hotel' OR
resortfacilities.h_id <> 35
with the expectation of get getting the following result
+----+---------------------------+-------+------+
| id | name | image | h_id |
+----+---------------------------+-------+------+
| 4 | Grillroom | | 38 |
| 2 | Minibar in alle Zimmer | | NULL |
| 3 | Snack restaurant | | NULL |
+----+---------------------------+-------+------+
with out the values that belongs to h_id 35 but I end up with
+----+---------------------------+-------+------+
| id | name | image | h_id |
+----+---------------------------+-------+------+
| 1 | Bar | | 38 |
| 4 | Grillroom | | 38 |
| 2 | Minibar in alle Zimmer | | NULL |
| 3 | Snack restaurant | | NULL |
+----+---------------------------+-------+------+
May I know how to get the that result?
use the below script (for getting the result as mentioned ).
SELECT
f.id,
f.`name`,
f.image,
r.h_id
FROM
facilities f
LEFT JOIN resortfacilities r ON f.id = f.f_id AND r.h_id <> 35
WHERE f.category = 'hotel'

listing corresponding data of two tables

i'm pretty new to sql and i have a problem that i coundn't really describe to google
SELECT name AS state
FROM state
WHERE id IN
(
SELECT state_id
FROM city
WHERE id=(SELECT city_id FROM zipcode)
)
;
This lists the states of all zipcodes I have in my database, I also want to list the zipcodes (zipcode.zipcode) in a additional column corresponding with the state
Thank you very much in advance for your help
my tables look like this:
city
+----+----------+-----------+---------------------+---------+---------+
| id | state_id | county_id | name | lat | lng |
+----+----------+-----------+---------------------+---------+---------+
| 1 | 1 | 1 | Prem, Oberbayern | 47.6833 | 10.8 |
| 2 | 2 | 2 | Pfullendorf (Baden) | 47.9249 | 9.25718 |
| 3 | 3 | 3 | Wissen, Sieg | 50.7833 | 7.75 |
| 4 | 1 | 4 | Miltenberg | 49.7039 | 9.26444 |
| 5 | 1 | 5 | Moosthenning | 48.6833 | 12.5 |
| 6 | 1 | 1 | Bernbeuren | 47.7333 | 10.7833 |
| 7 | 4 | 6 | Demmin, Hansestadt | 53.9 | 13.0333 |
| 8 | 2 | 7 | Konstanz, Universit | 47.6667 | 9.18333 |
| 9 | 5 | 8 | Teutschenthal | 51.45 | 11.8 |
| 10 | 6 | 9 | Vierlinden | 52.515 | 14.3141 |
+----+----------+-----------+---------------------+---------+---------+
zipcode
+----+---------+-------------+---------+
| id | city_id | district_id | zipcode |
+----+---------+-------------+---------+
| 1 | 1 | NULL | 86984 |
| 2 | 2 | NULL | 88630 |
| 3 | 3 | NULL | 57537 |
| 4 | 4 | NULL | 63897 |
| 5 | 4312 | 502 | 84164 |
| 6 | 6 | NULL | 86975 |
| 7 | 7 | 778 | 17109 |
| 8 | 8 | NULL | 78462 |
| 9 | 8 | NULL | 78464 |
| 10 | 8 | NULL | 78465 |
+----+---------+-------------+---------+
state
+----+------------------------+
| id | name |
+----+------------------------+
| 1 | Bayern |
| 2 | Baden-W?rttemberg |
| 3 | Rheinland-Pfalz |
| 4 | Mecklenburg-Vorpommern |
| 5 | Sachsen-Anhalt |
| 6 | Brandenburg |
| 7 | Niedersachsen |
| 8 | Schleswig-Holstein |
| 9 | Nordrhein-Westfalen |
| 10 | Th?ringen |
+----+------------------------+
Use explicit JOINs:
SELECT z.*, s.name AS state
FROM zipcode z JOIN
city c
ON z.city_id = c.id JOIN
state s
ON c.state_id = s.id;
If you are learning SQL, focus on learning JOIN rather than IN.