set default value on query column - mysql

I have a query with columns "Cremembers.Name" (this pulls the "Name" column from the table "Crewmembers") and "Sum of HoursUW" (this sums "HoursUW" from a different table "Marine391" per "Crewmember.Name". There is an existing relationship between Cremembers.Name and Marine391.Crewmembers where all Cremembers.Name values are listed and only values from Marine391.Crewmembers are listed where the joined fields are equal.
In this query, if a crewmember does not have any HoursUW, I want the default value of "Sum of HoursUW" to be 0.
This is the current SQL code:
SELECT DISTINCTROW Crewmembers.Name, Sum(Marine391_29ft_SAFEBOAT.HoursUW) AS [Sum Of HoursUW]
FROM Crewmembers LEFT JOIN Marine391_29ft_SAFEBOAT ON Crewmembers.[Name] = Marine391_29ft_SAFEBOAT.[Crewmembers].[Value]
GROUP BY Crewmembers.Name;
I tried using the nz() function like this:
nz((SELECT DISTINCTROW Crewmembers.Name, Sum(Marine391_29ft_SAFEBOAT.HoursUW), 0) AS [Sum Of HoursUW]
FROM Crewmembers LEFT JOIN Marine391_29ft_SAFEBOAT ON Crewmembers.[Name] = Marine391_29ft_SAFEBOAT.[Crewmembers].[Value]
GROUP BY Crewmembers.Name;
and like this:
SELECT DISTINCTROW Crewmembers.Name, nz(Sum(Marine391_29ft_SAFEBOAT.HoursUW), 0) AS [Sum Of HoursUW]
FROM Crewmembers LEFT JOIN Marine391_29ft_SAFEBOAT ON Crewmembers.[Name] = Marine391_29ft_SAFEBOAT.[Crewmembers].[Value]
GROUP BY Crewmembers.Name;
These both had syntax errors.
How can I use the nz() function or is there a better way to set the default value to 0 in this query?
Thanks in advance!!!

Apply Nz() directly to the HoursUW field as you Sum() it.
SELECT cm.Name, Sum(Nz(msb.HoursUW, 0)) AS [Sum Of HoursUW]
FROM
Crewmembers AS cm
LEFT JOIN Marine391_29ft_SAFEBOAT AS msb
ON cm.[Name] = msb.[Crewmembers].[Value]
GROUP BY cm.Name;
I did not include DISTINCTROW because the query's result set rows will already be distinct by virtue of the GROUP By.

Related

SQL Selecting count from join returning 0 instead of null result

I have a query that gets data and also joins another table (A) and counts the rows in that join table (B). However if the main table (A) is empty I want the query to return nothing. However it is returning a result of null for id and date and an integer value of 0 for users instead of a null row. How do I get an empty result instead of it returning something?
Returning:
id | date | users
null | null | 0
SQL Code
SELECT
`sessions`.`id`,
`sessions`.`date`,
COUNT( sessions_users.id ) AS users
FROM
`sessions`
LEFT JOIN `sessions_users` ON `sessions`.`id` = `sessions_users`.`sessions_id`
An aggregate query without a group by clause always returns a single record, regardless of the content of the underlying result set (and even if it is empty).
But, since you have non-aggregated columns in the select clause (sessions.id and sessions.date), your query is missing a group by clause anyway. In non-ancient versions in MySQL, where sql mode ONLY_FULL_GROUP_BY is enabled by default, this is a syntax error.
Consider:
SELECT
`sessions`.`id`,
`sessions`.`date`,
COUNT( sessions_users.id ) AS users
FROM
`sessions`
LEFT JOIN `sessions_users` ON `sessions`.`id` = `sessions_users`.`sessions_id`
GROUP BY
`sessions`.`id`,
`sessions`.`date`
This will produce one record per session id and date, along with the count of matching records in sessions_users. If there are no records in sessions, the query will return an empty result set.
If I understand correctly, instead of NULL, you want something like this:
id | date | users
| | 0
If so, just simply use IFNULL() in your SELECT as such:
SELECT
IFNULL(`sessions`.`id`,' ') as id,
IFNULL(`sessions`.`date`,' ') as date,
....
There are also a few other ways to achieve this using just IF() or CASE .. but IFNULL is very straight forward.
BUT if you don't want to see any NULL and 0 values, change your LEFT JOIN to INNER JOIN and you're done.
From your description, it sounds like you want an inner join:
SELECT s.id, s.date, COUNT(*) as users
FROM sessions s JOIN
sessions_users su
ON su.id = su.sessions_id;

Need to join SQL table with multiple match, if value doesn't matches it should return a blank/NA value

I want to join below tables in such a way that that it should return matched value if not matching it should return a value as "NA".
below are the table details
available tables:
desired output:
Use Left Join between the tables, to consider those rows also which do not exist in the Process table.
You can use Ifnull() function, to set the value NA if no matching row (thus null value) in the Process table.
Try the following (change table and column name(s) accordingly):
SELECT r.Ticket_id,
r.Status,
r.Department,
r.Owner,
r.Process_id,
IFNULL(p.Proces_Name, 'NA')
FROM Resolution AS r
LEFT JOIN Process AS p ON p.Process_id = r.Process_id
If a value isn't found in a MySQL LEFT JOIN, the field is "filled" with NULL
The best practice, as I understand your question is IFNULL
SELECT
r.*,
IFNULL(process_name,'NA')
FROM
resolution r
LEFT JOIN processes p ON p.process_id = r.process_id
select a.ticket_id,a.status,a.department,a.ownername,
case
when b.process_name is null then 'NA'
else b.process_name
end as proces_name
from resolution_tab a
left join process_tab b
on a.process_id=b.process_id
order by a.ticket_id;

Select another column on IN query (subquery)

I have a query that gets a sku_product product that is sold on a precise date
SELECT stock_products.`related_warehouse_position_id`, `product_code`, `EAN_CODE`, `custom_cart_picked_up`, `warehouse`, sum(`RemainingStock`), stock_products.`time_Picked_up`
FROM `product_warehouse_position`
INNER JOIN stock_products ON product_warehouse_position.id = stock_products.related_warehouse_position_id
WHERE stock_products.time_Picked_up < '2017-10-10'
GROUP BY product_code
HAVING SUM(RemainingStock) = 0
Now i've tried with this query but the result is wrong.
I've try to make a subquery, but i need to get a time_pickedUp which is located on stock_products table.
SELECT `id` ,`product_code`, `EAN_CODE`, `custom_cart_picked_up`, `warehouse`, sum(`RemainingStock`)
FROM product_warehouse_position
WHERE product_code IN (
SELECT product_stock_sku, time_Picked_up
FROM `stock_products`
WHERE stock_products.time_Picked_up < '2017-05-01'
)
GROUP BY product_warehouse_position.product_code
HAVING SUM(product_warehouse_position.`RemainingStock`) = 0
This query return an error :
Operand should contain 1 column(s).
How to solve this problem without change the structure of this query?
If your query is correct then the only thing you need to do is remove the column time_Picked_up from the select in your inner query. You can still filter on that column in your WHERE clause.

MIN() causing MySQL to return all-NULL row instead of 0 rows

I have two tables, services and extraFees, related 1xn through services.id = extraFees.serviceId. My problem is that when I execute the following query for a non-existing combination of s.id and s.category, I still get 1 row(s) returned, with all fields NULL.
SELECT 100 + (s.feeRate * MIN(ef.extra)) AS extraFees FROM services s
LEFT JOIN extraFees ef ON s.id=ef.serviceId WHERE s.id=12 AND s.category='PRG'
I know the culprit is MIN(), because if I replace it with a number or NULL, I get 0 row(s) returned, which is what I want.
SELECT 100 + (s.feeRate * 5) AS extraFees FROM services s
LEFT JOIN extraFees ef ON s.id=ef.serviceId WHERE s.id=12 AND s.category='PRG'
SELECT 100 + (s.feeRate * NULL) AS extraFees FROM services s
LEFT JOIN extraFees ef ON s.id=ef.serviceId WHERE s.id=12 AND s.category='PRG'
Why does this happen and how can I avoid it?
An aggregate function will return a result. Try this:
CREATE TABLE x(id int);
SELECT MIN(id) FROM x
and you will get 1 row: NULL. You can wrap in a subquery if you want to
ignore the NULL result:
SELECT y.id
FROM (SELECT MIN(id) AS id FROM x) y
WHERE y.id IS NOT NULL
or make use of the HAVING clause.
This happens because, MIN() returns NULL if there were no matching rows.
How can I avoid it?
Try to wrap the call to MIN() in a sub-query to filter out the NULL.
EDIT:
I've read that doc, but I don't see how the NULL returned by MIN() is
different from the NULL I manually specify in my last query.
I suspect this is because your second set of queries are not aggregate queries.
Aggregate queries will return the result of the aggregation on the rows.
If there are no rows then the query returns NULL.
On the other hand the second set of queries are not aggregate queries, those queries can return an 'empty set' as a logical result.

Finding even values in a table MySQL

In MySQL, i have a table with a column full of positive integers and i want to filter out all the odd integers. It seems like there is nothing in the MySQL documentation. I tried the following query.
select kapsule.owner_name,
kapsule.owner_domain,
count(xform_action)
from kapsule, rec_xform
where rec_xform.g_conf_id=kapsule.g_conf_id
and (count(xform_action))%2=0
group by kapsule.owner_name;
I want to keep only those values where count(xform_action) is even. The table looks like this.
To filter out resultset after GROUP BY you need to use HAVING clause.
WHERE clause is used to filter source rows before GROUP BY occurs.
Try
SELECT k.owner_name,
k.owner_domain,
COUNT(x.xform_action) cnt -- < you probably meant to use SUM() instead of COUNT() here
FROM kapsule k JOIN rec_xform x -- < use JOIN notation for clarity
ON x.g_conf_id = k.g_conf_id
GROUP BY k.owner_name
HAVING cnt % 2 = 0
You probably meant to use SUM() (sums values of a column of all rows in a group) aggregate instead of COUNT() (returns number of rows in a group)
Here is SQLFiddle demo (for both SUM() and COUNT())
For aggregate functions like COUNT(*) using GROUP BY you need to use HAVING clause
select kapsule.owner_name, kapsule.owner_domain,
count(xform_action) from kapsule, rec_xform
where rec_xform.g_conf_id=kapsule.g_conf_id and
group by kapsule.owner_name, kapsule.owner_domain
HAVING (count(xform_action))%2=0
or you could use alias (i.e. AS) like:
select kapsule.owner_name, kapsule.owner_domain,
count(xform_action) count_form from kapsule, rec_xform
where rec_xform.g_conf_id=kapsule.g_conf_id and
group by kapsule.owner_name, kapsule.owner_domain
HAVING count_form%2=0
And you could use JOIN as more efficient than the old one of joining tables. And by the way
if you have GROUP BY the fields before the aggregate function should be in GROUP BY like:
select kapsule.owner_name, kapsule.owner_domain,
count(xform_action) count_form from kapsule A
INNER JOIN rec_xform B
ON A.g_conf_id=B.g_conf_id and
GROUP BY by A.owner_name, A.owner_domain
HAVING count_form%2=0
See examples here