Mysql join not showing all records - mysql

I am using Php with join, I have two tables ("services" and "service_detail"), I want to get all services
but want to know which service selected or notselected by vendor
Here is my services table strcture
id service_name image
1 Abc abc.jpg
2 xyz xyz.jpg
3 OPS ops.jpg
4 tys tys.jpg
5 byp byp.jpg
Here is my services_detail table strcutre
id vendor_id service_id price
1 101 1 50
2 101 2 70
3 101 3 80
4 101 4 30
5 102 1 70
6 102 2 40
...
I tried with following query but showing only selected services, but i want to get all services with parameter ( selected or notselected)
Where i am wrong ? Here is my query
SELECT sd.vendor_id, sd.service_id, sd.price, s.service_name, s.image
FROM services_detail sd
LEFT JOIN services s
ON sd.service_id = s.id
WHERE sd.vendor_id = '101'

Move your where clause to be AND in ON clause:
AND sd.vendor_id = '101'
And interchange tables in join to get all servcies
SELECT sd.vendor_id, sd.service_id, sd.price, s.service_name, s.image,
IF (sd.vendor_id is not null, 'Opted', 'Not opted') as status
FROM services s
LEFT JOIN services_detail sd
ON sd.service_id = s.id AND sd.vendor_id = '101';
In simple words, when there is a where clause including filters on table of Left Join then it will act like INNER JOIN not LEFT JOIN.

Related

Trying to get latest status for related shipment but the results I receive are incorrect

I am currently working on a project while trying to learn MySQL and I would like to join three tables and get the latest status for each related shipment. Here are the tables I'm working with (with example data):
shipments
id
consignee
tracking_number
shipper
weight
import_no
1
JOHN BROWN
TBA99900000121
AMAZON
1
101
2
HELEN SMITH
TBA99900000190
AMAZON
1
102
3
JACK BLACK
TBA99900000123
AMAZON
1
103
4
JOE BROWM
TBA99900000812
AMAZON
1
104
5
JULIA KERR
TBA99900000904
AMAZON
1
105
statuses
id
name
slug
1
At Warehouse
at_warehouse
2
Ready For Pickup
ready_for_pickup
3
Delivered
delivered
shipment_status (pivot table)
id
shipment_id
status_id
1
1
1
2
2
1
3
3
1
4
4
1
5
5
1
6
1
2
7
2
2
8
3
2
9
4
2
10
5
2
all tables do have created_at and updated_at timestamp columns
Example of the results I'm trying to achieve
slug
shipment_id
status_id
ready_for_pickup
1
2
ready_for_pickup
2
2
ready_for_pickup
3
2
ready_for_pickup
4
2
ready_for_pickup
5
2
Here's the query I wrote to try to achieve what I'm looking for based on examples and research I did during the past couple of days. I find that sometimes there is sometimes a mismatch with the latest status that relates to the shipment
SELECT
statuses.slug AS slug,
MAX(shipments.id) AS shipment_id,
statuses.id AS status_id,
FROM
`shipments`
INNER JOIN `shipment_status` ON `shipment_status`.`shipment_id` = `shipments`.`id`
INNER JOIN `statuses` ON `shipment_status`.`status_id` = `statuses`.`id`
GROUP BY
`shipment_id`
Because we need to reference other fields from the same record that evaluates from the MAX aggregation, you need to do it in two steps, there are other ways, but I find this syntax simpler:
SELECT
shipments.id AS id,
statuses.slug AS slug,
statuses.id AS status_id,
shipment_status.shipment_id as shipment_id
FROM
`shipments`
INNER JOIN `shipment_status` ON `shipment_status`.`shipment_id` = `shipments`.`id`
INNER JOIN `statuses` ON `shipment_status`.`status_id` = `statuses`.`id`
WHERE
shipment_status.id = (
SELECT MAX(shipment_status.id)
FROM `shipment_status`
WHERE shipment_status.shipment_id = shipments.id
)
try it out!
This query makes the assumption that the id field is an identity column, so the MAX(shipment_status.id) represents only the most recent status for the given shipment_id
You can use window functions:
SELECT s.id, st.slug, st.id
FROM shipments s JOIN
(SELECT ss.*,
ROW_NUMBER() OVER (PARTITION BY shipment_id ORDER BY ss.id DESC) as seqnum
FROM shipment_status ss
) ss
ON ss.shipment_id = s.id JOIN
statuses st
ON ss.status_id` = st.id
WHERE ss.seqnum = 1;
Also note the use of table aliases so the query is easier to write and to read.

SQL inner join with max function by groub

I have some problem from using the inner join with group by using max function.
my detail :
Table inventory
site_ID tank_number volume times-tramp ID
1 1 5000 06/08/2017 15:00 1
1 1 4900 06/08/2017 15:01 2
1 2 6000 06/08/2017 15:05 3
1 3 4000 06/08/2017 15:05 4
2 1 3000 06/08/2017 15:33 5
2 2 2000 06/08/2017 15:34 6
1 1 4800 06/08/2017 15:36 7
1 2 5800 06/08/2017 16:00 8
Table wp_users (wordpress)
ID Name
1 aaa
2 bbbb
Now, I using with wpdatatable plugin in wordpress so i want use the inner join and group with tank_number and using data update by times-strap
The result should be is :
When user "aaa" login then ID will is 1
the result that want to show.
site_ID tank_number volume times-tramp
1 1 4800 06/08/2017 15:36
1 2 5800 06/08/2017 16:00
1 3 4000 06/08/2017 15:05
But
I got the this result :
site_ID tank_number volume times-tramp
1 1 5000 06/08/2017 15:00
1 2 6000 06/08/2017 15:05
1 3 4000 06/08/2017 15:05
So can every one help to advise me so I have show my code the showing the error due to i can't join with 2 table by correct syntax sql.
this code can work without inner join
select site_id, tank_product, volume, timestramp from inventory as t1
inner join (
select tank_product as tank, max(timestramp) as time from inventory
where site_id=1 group by tank_product) as t2
on t1.tank_product = t2.tank and t1.timestramp = t2.time and t1.site_id=1
and Now I trying to using with inner join but not work now.
SELECT inventory.site_id,
inventory.tank_product,
inventory.volume,
inventory.timestramp,
wp_users.ID
FROM inventory as t1
INNER JOIN wp_users
(SELECT inventory.tank_product, max(inventory.timestramp) as time from inventory
WHERE inventory.site_id=wp_users.ID GROUP BY inventory.tank_product) as t2
ON t1.inventory.tank_product=t2.tank AND t1.inventory.timestramp=t2.time AND t1.inventory.site_id=wp_users.ID
Can advise me for correct way to use the inner join by group by max function.
So, the schema you present and the queries you provided don't line up (naming is all over the place). It would be very helpful if you provided a sql fiddle to help present your problem (at least in the future).
In any event, I think you were close:
select t2.site_id, t2.tank_product, t1.volume, t2.time
from (
select site_id, tank_product, max(timestramp) as time
from inventory
group by site_id,tank_product) t2
inner join inventory t1
on t2.site_id=t1.site_id and t1.tank_product=t2.tank_product and t2.time=t1.timestramp
inner join wp_users u
on u.id=t2.site_id
where u.id=1
order by t2.site_id,t2.tank_product asc
(Assuming you pass the wp_users.id into the query; I've hard-coded that with u.id=1.)
fiddle
Try to run this:
SELECT i1.site_ID, i1.tank_product, i1.volume, i.timestramp, iu.User_ID
FROM Inventory AS i1
INNER JOIN (
SELECT u.ID AS UserID, i.tank_product, MAX (i.timestramp) AS time
FROM Inventory AS i2
INNER JOIN wp_users AS u
ON i2.site_id = u.ID
GROUP BY u.ID, i.tank_product
) as iu
ON i1.tank_product = iu.tank_product
AND i1.timestramp = iu.time
AND i1.site_ID = iu.UserID;

Mysql union, left join, group and count

Heres my query
SELECT
fsi_courier_assignment_print_master_listing.master_listing_id,
fsi_master_listing.transmittal_id,
fsi_transmittals.product_name,
fsi_transmittals.transmittal_id
FROM fsi_courier_assignment_print_master_listing
LEFT JOIN fsi_master_listing ON fsi_courier_assignment_print_master_listing.master_listing_id = fsi_master_listing.master_listing_id
LEFT JOIN fsi_transmittals ON fsi_master_listing.transmittal_id = fsi_transmittals.transmittal_id
WHERE dispatch_code_id=".$this->db->escape($dispatch_code_id)."
UNION ALL
SELECT
fsi_courier_assignment_print_master_listing_undelivered.master_listing_id,
fsi_master_listing.transmittal_id,
fsi_transmittals.product_name,
fsi_transmittals.transmittal_id
FROM fsi_courier_assignment_print_master_listing_undelivered
LEFT JOIN fsi_master_listing ON fsi_courier_assignment_print_master_listing_undelivered.master_listing_id = fsi_master_listing.master_listing_id
LEFT JOIN fsi_transmittals ON fsi_master_listing.transmittal_id = fsi_transmittals.transmittal_id
WHERE dispatch_code_id=".$this->db->escape($dispatch_code_id)."
fsi_courier_assignment_print_master_listing table
master_listing_id dispatch_code_id
2 2
5 2
36 2
37 2
134 2
135 2
136 2
137 2
138 2
139 2
140 2
fsi_courier_assignment_print_master_listing_undelivered table
master_listing_id dispatch_code_id
1 2
fsi_master_listing table
master_listing_id transmittal_id
1 1
2 1
5 2
36 2
37 2
134 3
135 3
136 3
137 3
138 3
139 3
140 3
fsi_transmittals table
transmittal_id product_name
1 Name 1
2 Name 2
3 Name 3
What Im trying to do is to get the combined result of product from fsi_courier_assignment_print_master_listing and fsi_courier_assignment_print_master_listing_undelivered where dispatch_code_id='2' and count them
My desire Output would be
Product Name Product Count
Name 1 2
Name 2 3
Name 3 7
Thanks in advance, hope somebody can help me to this..
Your query is fine, you just need to:
Add COUNT with GROUP BY product_name and put your query as a subquery.
The transmittal_id is specified two times in the two union queries, either remove one of them or give them different names (It might work fine in MySQL, but it is recommended not to do so).
So your query will be something like this:
SELECT
t.product_name,
COUNT(*) AS ProductCount
FROM
(
SELECT
ml.master_listing_id,
m.transmittal_id,
t.product_name
FROM fsi_courier_assignment_print_master_listing AS ml
LEFT JOIN fsi_master_listing AS m
ON ml.master_listing_id = m.master_listing_id
LEFT JOIN fsi_transmittals AS t
ON m.transmittal_id = t.transmittal_id
UNION ALL
SELECT
u.master_listing_id,
m.transmittal_id,
t.product_name
FROM fsi_courier_assignment_print_master_listing_undelivered as u
LEFT JOIN fsi_master_listing AS m
ON u.master_listing_id = m.master_listing_id
LEFT JOIN fsi_transmittals AS t
ON m.transmittal_id = t.transmittal_id
) AS t
GROUP BY t.product_name;
This will give you:

Difficult sql request

I've got some troubles with a sql request.
Here are my tables :
text :
id component_kind text
56 4 a
19 4 a
10 4 a
1 6 b
act :
id text_id detail_id detail_type
1 56 2 ItemGather
2 19 5 MonsterHunt
3 10 6 ItemUse
ItemGather :
id item_id count
2 1020 3
MonsterHunt :
id npc_id count
5 256 10
ItemUse :
id item_id count
6 3241 1
As you can see act.text_id is a foreign key of text.id and act.detail_id represents the id of one of the tables below act.
What I want to do is show something like this :
component_kind text gather_id gather_count use_id use_count hunt_id hunt_count
4 a 1020 3 3241 1 256 10
6 b 0 0 0 0 0 0
I don't know what to write in my request. Can any sql pro help me?
As mentioned in the comments above, simply outer-join the tables.
I use GROUP_CONCAT for the case that there is more than one match. In MySQL it would be allowed to simply select ig.item_id instead of group_concat(ig.item_id) which would give you a random ID in case there is more than one. It's up to you what you want to show in this case.
I use COALESCE to show 0 instead of NULL for sums when there are no matching records.
select
t.component_kind,
t.text,
group_concat(ig.item_id) as gather_ids,
coalesce(sum(ig.count),0) as gather_count,
group_concat(iu.item_id) as use_ids,
coalesce(sum(iu.count),0) as use_count,
group_concat(mh.npc_id) as hunt_is,
coalesce(sum(mh.count),0) as hunt_count
from text t
left outer join act a on a.text_id = t.id
left outer join itemgather ig on ig.id = a.detail_id and a.detail_type = 'ItemGather'
left outer join monsterhunt mh on mh.id = a.detail_id and a.detail_type = 'MonsterHunt'
left outer join itemuse iu on iu.id = a.detail_id and a.detail_type = 'ItemUse'
group by t.component_kind, t.text;
Here is the SQL fiddle: http://sqlfiddle.com/#!2/00cfb/10.

Multiple Counts from many INNER JOIN tables with Conditions

I'm having a lot of trouble figuring out how to write this query. Here's an exmaple of the data set and what I need to query:
**System Table**
SystemID Active
1 T
2 T
3 T
4 F
5 F
6 F
**BlogPost Table**
BlogPostID SystemID Create_Month
100 2 Jan
101 2 Jan
102 2 Feb
103 3 Feb
104 3 Mar
105 6 Mar
106 6 Mar
**Comment Table**
Comment ID BlogPostID Liked
201 100 T
202 100 T
203 100 T
204 102 T
205 102 T
206 102 T
207 103 F
So, In words, I'm trying to get: By month, show me all the active systems who created a post during that month, the number of posts they made in aggregate, and the count of the subset of those posts who had a comment that was like.
The end result would be like:
Column 1 - Month
Column 2 - Count of Active Systems where a Post Created in Month
Column 3 - Count of Posts Applicable to those systems
Column 4 - Count of Applicable Posts that had comments that were liked
I don't even know where to start really. My terrible "this is obviously wrong" attempt is below. Any help is much appreciated, thanks!
SELECT
Month,
COUNT(DISTINCT system.systemid),
COUNT(blogpost.BlogPostID)
COUNT(comments.commentiD)
FROM
system INNER JOIN
blogpost ON system.systemid = blogpost.systemid INNER JOIN
comments ON blogpost.BlogPostID = comment.BlogPostID
WHERE
system.active = T
AND comments.like = T
GROUP BY month
A complicated one !
SELECT
b.Create_Month,
COUNT(DISTINCT s.SystemID) as SystemCount,
COUNT(DISTINCT b.BlogPostID) as PostsCount,
COUNT(DISTINCT t.BlogPostID) as PostsWithLike
FROM System s
JOIN BlogPost b
ON s.systemID = b.systemID
AND s.Active = 'T'
LEFT JOIN Comment c
ON b.BlogPostID = c.BlogPostID
LEFT JOIN
(
SELECT DISTINCT c.BlogPostID as BlogPostID
FROM
Comment c
GROUP BY c.BlogPostID
HAVING SUM(if(c.Liked='T',1,0))>0
) as t
ON b.BlogPostID = t.BlogPostID
GROUP BY b.Create_Month
This is probably what you want :
SELECT s.systemid, active, bp.create_month, bp.systemid, COUNT(bp.blogpostid), COUNT(c.liked)
FROM system AS s
LEFT OUTER JOIN Blogpost AS bp ON s.systemid = bp.systemid
LEFT OUTER JOIN Comment AS c ON bp.blogpostid = c.blogpostid
WHERE active = 'T' AND c.Liked = 'T' GROUP BY s.systemid,bp.create_month