Why INNER JOIN dont not work correct? - mysql

I have one SQL query with INNER JOINS. I need to get all offers from table offers.
Table offers is empty now. But the following query returns one row with NULL field.
Why is it returned? How to fix that? I need to return 0 rows if table is empty.
Query:
select *, SUM(offers.price * announcement_product.amount) AS total, announcements.user_id AS creator_ann, announcements.id AS ann_id,
announcements.delivery AS deliveryAnn, announcements.payment AS
paymentAnn, SUM(announcement_product.amount) AS amount,
announcement_product.name as name_product
from `offers`
inner join `announcements` on `announcements`.`id` = `offers`.`announcement_id`
inner join `announcement_product` on `offers`.`announcement_product_id` = `announcement_product`.`id`
inner join `countries` on `countries`.`id` = `announcements`.`country`
where `offers`.`user_id` = 1 and `offers`.`status` = 1 and `offers`.`deleted_at` is null

You're using the aggregate function SUM(), but you don't have any GROUP BY clause.
When you do that you are instructing MySQL to add up all the row values in the column you mention in SUM(). It will do that even if there are no rows to add up.
For best results you should study up on the GROUP BY function and how to use it with SUM(). It's hard to guess what you want from your query.

I'm not sure, but I don't think
select *, ..
when there's multiple tables in the query is valid.
Try
select offers.*,..

This how Your select structure should be :
Select
Id,
Sku,
Sum(Onhand),
Sum(price)
From mytable
Where mytable Onhand > 0
Group by
Id,Sku
If you are going to use aggregate function such as Max,Sum,Min,....
you need to use group by for other table fields that your using in the select part.

Related

MySQL query returns false if a COUNT-SELECT in the query returns nothing

Using the following, I'm getting a null set because the inner select returns nothing. I want the results of the wishlist table entry (which is there) with 0 for the count. I thought this would do it, but apparently not?
SELECT *, (
SELECT COUNT(*)
FROM wl_items
WHERE wl_id = wishlists.id
) as item_count
FROM wishlists
WHERE wishlists.id=5
This query feels like you could do it more simply as a join:
SELECT wishlists.*, COUNT(wl_id)
FROM wishlists LEFT JOIN wl_items ON (wl_id = wishlists.id)
WHERE wishlists.id=5;

Incorrect group by and order by merge

I have couple tables joined in MySQL - one has many others.
And try to select items from one, ordered by min values from another table.
Without grouping in seems to be like this:
Code:
select `catalog_products`.id
, `catalog_products`.alias
, `tmpKits`.`minPrice`
from `catalog_products`
left join `product_kits` on `product_kits`.`product_id` = `catalog_products`.`id`
left join (
SELECT MIN(new_price) AS minPrice, id FROM product_kits GROUP BY id
) AS tmpKits on `tmpKits`.`id` = `product_kits`.`id`
where `category_id` in ('62')
order by product_kits.new_price ASC
Result:
But when I add group by, I get this:
Code:
select `catalog_products`.id
, `catalog_products`.alias
, `tmpKits`.`minPrice`
from `catalog_products`
left join `product_kits` on `product_kits`.`product_id` = `catalog_products`.`id`
left join (
SELECT MIN(new_price) AS minPrice, id FROM product_kits GROUP BY id
) AS tmpKits on `tmpKits`.`id` = `product_kits`.`id`
where `category_id` in ('62')
group by `catalog_products`.`id`
order by product_kits.new_price ASC
Result:
And this is incorrect sorting!
Somehow when I group this results, I get id 280 before 281!
But I need to get:
281|1600.00
280|2340.00
So, grouping breaks existing ordering!
For one, when you apply the GROUP BY to only one column, there is no guarantee that the values in the other columns will be consistently correct. Unfortunately, MySQL allows this type of SELECT/GROUPing to happen other products don't. Two, the syntax of using an ORDER BY in a subquery while allowed in MySQL is not allowed in other database products including SQL Server. You should use a solution that will return the proper result each time it is executed.
So the query will be:
For one, when you apply the GROUP BY to only one column, there is no guarantee that the values in the other columns will be consistently correct. Unfortunately, MySQL allows this type of SELECT/GROUPing to happen other products don't. Two, the syntax of using an ORDER BY in a subquery while allowed in MySQL is not allowed in other database products including SQL Server. You should use a solution that will return the proper result each time it is executed.
So the query will be:
select CP.`id`, CP.`alias`, TK.`minPrice`
from catalog_products CP
left join `product_kits` PK on PK.`product_id` = CP.`id`
left join (
SELECT MIN(`new_price`) AS "minPrice", `id` FROM product_kits GROUP BY `id`
) AS TK on TK.`id` = PK.`id`
where CP.`category_id` IN ('62')
order by PK.`new_price` ASC
group by CP.`id`
The thing is that group by does not recognize order by in MySQL.
Actually, what I was doing is really bad practice.
In this case you should use distinct and by catalog_products.*
In my opinion, group by is really useful when you need group result of agregated functions.
Otherwise you should not use it to get unique values.

triple nested mysql selects returns no results when it should

This SQL Query
(SELECT * FROM OperatorRoster as roster
INNER JOIN ( SELECT *, count(*) as activeSlots FROM Connectors
group by (operator)) as connectors
ON connectors.operator = roster.operator)
Workes fine and return all the values that i need, but i need to use the restult in a new query
but if i try to use it:
SELECT * FROM (SELECT * FROM OperatorRoster as roster
INNER JOIN ( SELECT *, count(*) as activeSlots FROM Connectors
group by (operator)) as connectors
ON connectors.operator = roster.operator) as q
It returs nothing.
how can i query this subquery?
you are missing an ON clause of the main join .
on q.___= Operators.___
Since you are using an inner join, are you sure that there exist rows where
connectors.operator=roster.operator
if there are no rows that match that requirement then your query shouldn't return any rows
Turns out that since I did a join on operators but select all fields,
(SELECT * FROM OperatorRoster as roster
INNER JOIN ( SELECT *, count(*) as activeSlots FROM Connectors
group by operator) as connectors
ON connectors.operator = roster.operator)
It returns two fields with the same name "connectors.operator" and "roster.operator", and since the last select cant inherit the scoop, it conflicts.
No clued why it did not return an error but I fixed it by only selecting one operator field.

Getting row with maximum column value in mysql

I have been struggling with this.I had tried all the approaches like left outer join,group by and even sub queries but couldn't succeed.
Here is my query.
select star_ident,transition_ident,fix_ident,sequence_num,route_type
from corept.std_star_leg where data_supplier='J' and airport_ident='KMMU';
From the above result set i need to extract those rows that has maximum sequence_num for a given transition_ident and star_ident.
Here is my query.
select star_ident,transition_ident,fix_ident,max(sequence_num)
from corept.std_star_leg where data_supplier='J' and airport_ident='KMMU'
group by transition_ident,star_ident;
But the above query is producing wrong results.I even tried joins.
select yt1.star_ident,yt1.transition_ident,yt1.fix_ident
from corept.std_star_leg yt1
left outer join corept.std_star_leg yt2
on (yt1.star_ident = yt2.star_ident and yt1.transition_ident=yt2.transition_ident and yt1.sequence_num < yt2.sequence_num)
where yt1.airport_ident='KMMU' and yt1.data_supplier='J'
and yt2.airport_ident='KMMU' and yt2.data_supplier='J' and yt2.star_ident is null;
But i end up with zero rows.Provide me an efficient way to do this.I need to run this query for 13K entries.Thank you.
You are having nonaggregated columns in your select which are not part of group by.
FROM
MYSQL DOCS
MySQL extends the use of `GROUP BY` so that the select list can refer to nonaggregated
columns not named in the GROUP BY clause. You can use this feature to get better
performance by avoiding unnecessary column sorting and grouping. However, this is
useful primarily when all values in each nonaggregated column not named in the
GROUP BY are the same for each group. The server is free to choose any value from
each group, so unless they are the same, the values chosen are indeterminate.
So to get proper result add all the column of select in group by
EDIT
select b.*
from
corept.std_star_leg b
inner join
(select star_ident,transition_ident,max(sequence_num) as seq
from corept.std_star_leg where data_supplier='J' and airport_ident='KMMU'
group by star_ident,transition_ident) a
on b.star_ident = a.star_ident and a.transition_ident = b.transition_ident and
b.sequence_num = a.seq;
Hope it helps....
Try this:
SELECT *
FROM
(SELECT *
FROM table1
ORDER BY seqno DESC) tmp
GROUP BY `star_ident`,
`trans`
Here is the sqlfiddle
remove group by start_ident
select star_ident,transition_ident,fix_ident,max(sequence_num)
from corept.std_star_leg where data_supplier='J' and airport_ident='KMMU'
group by transition_ident

Mysql: WHERE statement that depends of the COUNT() of a column?

I've read loads of answers on SO, but still can't get this to work. I'm pretty sure I need a subquery but don't know where I should begin...
Here's readable/psuedo of what i want to do:
SELECT DISTINCT cat_sub.*, COUNT(job.job_id) AS num_properties_which_meet_criteria
FROM cat_sub
LEFT JOIN job_cat USING (sc_id)
LEFT JOIN job USING (job_id)
WHERE job.village_id=2 AND num_properties_which_meet_criteria > 0
GROUP BY sc_id
I'm trying to make my WHERE reference the amount of valid results in the job table, which in this instance are those which matchjob.village_id=2.
So just to make clear, i don't want the total number of rows matched by the join. I want to total num rows matched by the join and meeting the WHERE criteria.
Really appreciate any help!
You test the value of an aggregate function with a HAVING clause.
SELECT DISTINCT cat_sub.*, COUNT(job.job_id) AS num_properties_which_meet_criteria
FROM cat_sub
LEFT JOIN job_cat USING (sc_id)
LEFT JOIN job USING (job_id)
WHERE job.village_id=2
GROUP BY sc_id
HAVING COUNT(job.job_id) > 0
Use having instead of where:
WHERE job.village_id=2
GROUP BY sc_id
HAVING num_properties_which_meet_criteria > 0
You need to have a "HAVING" clause, there you can use conditions on aggregate functions used in the SELECT part of the query.
Did you try:
SELECT DISTINCT cat_sub.*, COUNT(job.job_id)
FROM cat_sub
LEFT JOIN job_cat USING (sc_id)
LEFT JOIN job USING (job_id)
WHERE job.village_id=2
GROUP BY sc_id
HAVING COUNT(job.job_id) > 0
UPDATE: Removed alias