Mysql exclusive left join on one to many relationship - mysql

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'

Related

Self join with counts on a nested categories table

I have a listing_categories table that has many listing_plans and listings, and many subcategories. I am trying to write a view to show the listing categories with listing_plan count, listings count and subcategory count.
Here is my listing_categories table:
MariaDB [railsapp_development]> describe listing_categories;
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| website_id | int(11) | YES | MUL | NULL | |
| listing_category_id | int(11) | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
| slug | varchar(255) | YES | | NULL | |
| description | text | YES | | NULL | |
| category_card | text | YES | | NULL | |
| listing_card | text | YES | | NULL | |
| layout | varchar(255) | YES | | NULL | |
| status | int(11) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
| keywords | varchar(255) | YES | | NULL | |
+---------------------+--------------+------+-----+---------+----------------+
And the view I am trying to write:
create or replace view `listing_category_details` AS
select
cats1.*,
count(l.id) as listing_count,
count(cats2.id) as subcategory_count,
count(lp.id) as plan_count
from
listing_categories as cats1
left join
listings as l on cats1.id = l.listing_category_id
left join
listing_plans as lp on cats1.id = lp.listing_category_id
inner join
listing_categories as cats2 on cats1.listing_category_id = cats2.id
group by
cats1.id
order by
cats1.name asc;
The output is incorrect, it is not showing the right count, as follows:
MariaDB [railsapp_development]> select id, slug, name, listing_count, subcategory_count, plan_count from listing_category_details limit 10;
+----+-------------------+-------------------+---------------+-------------------+------------+
| id | slug | name | listing_count | subcategory_count | plan_count |
+----+-------------------+-------------------+---------------+-------------------+------------+
| 17 | ares | Ares | 22 | 22 | 22 |
| 30 | automotive | Automotive | 16 | 16 | 16 |
| 19 | crist-osinski-inc | Crist-Osinski Inc | 12 | 12 | 12 |
| 29 | esl-cologne | ESL Cologne | 20 | 20 | 20 |
| 18 | executive-office | Executive Office | 22 | 22 | 22 |
| 27 | gfinity-london | GFinity London | 24 | 24 | 24 |
| 25 | hephaestus | Hephaestus | 28 | 28 | 28 |
| 24 | iem-championship | IEM Championship | 14 | 14 | 14 |
| 26 | league-all-stars | League All Stars | 30 | 30 | 30 |
| 21 | machinery | Machinery | 14 | 14 | 14 |
+----+-------------------+-------------------+---------------+-------------------+------------+
In the above example none of the figures are corect, for instance each listing_category has exactly 2 plans.
What am I doing wrong?
Use COUNT(DISTINCT):
select cats1.*,
count(distinct l.id) as listing_count,
count(distinct cats2.id) as subcategory_count,
count(distinct lp.id) as plan_count
from listing_categories cats1 left join
listings l
on cats1.id = l.listing_category_id left join
listing_plans lp
on cats1.id = lp.listing_category_id inner join
listing_categories cats2
on cats1.listing_category_id = cats2.id
group by cats1.id
order by cats1.name asc;
COUNT() just counts the number of non-NULL values. You are joining along a hierarchy, so the rows get multiplied as you descend the hierarchy.

How can I merge multiple rows with same ID into one row?

How can I merge multiple rows with same ID into one row.
I have table:
+----+------+------+------+
| ID | A | B | C |
+----+------+------+------+
| 1 | 123 | 31 | 456 |
| 1 | 412 | NULL | 1 |
| 2 | 567 | 38 | 4 |
| 2 | 567 | NULL | NULL |
| 3 | 2 | NULL | NULL |
| 3 | 5 | NULL | NULL |
| 4 | 6 | 1 | NULL |
| 4 | 8 | NULL | 5 |
| 4 | NULL | NULL | 5 |
+----+------+------+------+
I want to have table :
I have table:
+----+-----+------+------+-----+------+------+------+------+----+
| ID | A | B | C | A2 | B2 | C2 | A3 | B3 | C3 |
+----+-----+------+------+-----+------+------+------+------+----+
| 1 | 123 | 31 | 456 | 412 | NULL | 1 | | | |
| 2 | 567 | 38 | 4 | 567 | NULL | NULL | | | |
| 3 | 2 | NULL | NULL | 5 | NULL | NULL | | | |
| 4 | 6 | 1 | NULL | 8 | NULL | 5 | NULL | NULL | 5 |
+----+-----+------+------+-----+------+------+------+------+----+
Try This:-
1 :- Please Change data table structure to disallow null value.
Query :-
SELECT
GROUP_CONCAT(if (`A` ='0', 'NOVAL', `A`)SEPARATOR '----') as A,
GROUP_CONCAT(if (`B` ='0', 'NOVAL', `B`)SEPARATOR '----') as B,
GROUP_CONCAT(if (`C` ='0', 'NOVAL', `C`)SEPARATOR '----') as C
FROM que1
GROUP BY id
Now You can get the value using mysql_fetch_array

MYSQL multible inner join too long time

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.

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 |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+

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.