how to get GROUP data from multiple tables msSQL - mysql

tblDailyProduction
+---------+------------+------------+------------+----------+----------+
| date | items | quantity| weight| wheatConsumed| |
+---------+------------+------------+------------+----------+----------+
tblCashBillbook
+---------+------------+------------+------------+----------+----------+
+---------+------------+------------+------------+----------+----------+
| date | bagWeight | totalBags |
+---------+------------+------------+------------+----------+----------+
SELECT CAST(tblDailyProduction.date AS DATE) as DateField,
SUM(tblDailyProduction.quantity * tblDailyProduction.weight)
AS totalProduct,SUM(tblCashBillbook.totalBags * tblCashBillbook.bagWeight)
AS totalIssued
FROM tblDailyProduction
left join tblCashBillbook on tblDailyProduction.date=tblCashBillbook.date
GROUP BY CAST(tblDailyProduction.date AS DATE)
I want to Group data according to the date from two different tables using a JOIN clause. Getting the data from tblDailyProduction table but NULL from the tblCashBillBook table.
tried INNER, LEFT and RIGHT joins but there is a problem with the GROUP BY clause.

You don't need to group by both dates, as the dates are put together in your join statement.
Try changing it to:
GROUP BY dateField
What might be causing some problem is that you are doing a left join, so not every row will have a tblCashBillbook.date value. If they do, you shouldn't be using a left join but an inner join. So, you are trying to group by something that might be null in some rows, so again, I suggest you just group by the tblDailyProduction date column.

Related

How to add columns to another table based on one column?

I have my shop database and I want to join two tables together.
id_order | reference | id_shop_group | id_shop | id_carrier | id_lang | id_customer | id_cart
This the header row of my orders table and below is the header of customers table.
id_customer | id_shop_group | id_shop | id_gender | firstname | lastname
What I want to do is to join them based on id_customer column. More specifically I want to add all columns of customers except the ones that are already there to orders table based onid_customer. After joining the tables should look like this:
id_order|reference|id_shop_group|id_shop|id_carrier|id_lang|id_customer|id_cart|id_gender|firstname|lastname
When searching for a solution I found INNER JOIN keyword, but I'm not sure how to use it the way I want.
We don't "Add columns to a table". We, instead, submit SQL to the database that returns the result set that we want. In your case we want to Join the two tables and we can do that using an INNER JOIN on your id_customer field that is common between the two tables. We can turn that into it's own table if you want to hold, permanently, those results. It would look something like
SELECT
orders.id_order,
orders.reference,
orders.id_shop_group,
orders.id_shop,
orders.id_carrier,
orders.id_lang,
orders.id_customer,
orders.id_cart,
customer.id_gender,
customer.firstname,
customer.lastname
FROM orders INNER JOIN customer on orders.id_customer = customer.id_customer;
You can tweak the list of fields to be returned from the joining of these tables to suit your needs.
The fact that id_shop and id_shop_group are in both tables suggests they are part of a composite key. You may need to join using all three shared columns to guarantee unique rows. Otherwise you may retrieve duplicate order rows where the customer belongs to more than one shop.
e.g.
SELECT
...
FROM orders INNER JOIN customer on orders.id_customer = customer.id_customer
and orders.id_shop_group = customer.id_shop_group
and orders.id_shop = customer.id_shop

Query to return sales excludes results that are 0

I've searched this and found this problem, and the solution that worked for most people (using an outer join) is not working for me. I originally had an inner join, and switched it to an outer join but I am getting the same results. This is based off certain account numbers and it shows their total sales. If an account has 0 sales it does not show up, and I need it to show up. Here is my query.
Select a.accountnumber, SUM(a.totalsales) as Amount, c.companyname
FROM Sales a LEFT OUTER JOIN Accounts c on (a.Accountnumber = c.Accountnumber)
WHERE a.Salesdate between '1/1/2016' and '1/27/2016'
AND a.Accountnumber in ('1','2','3','4')
GROUP BY a.Accountnumber, c.companyname
And I'll get results like:
Accountnumber | Amount | Company
1 | 250.00 | A
3 | 500.00 | B
Since accountnumbers 2 and 4 dont have an amount, they are not showing up. I would like them to show up like
Accountnumber | Amount | Company
1 | 250.00 | A
2 | 0 | B
3 | 250.00 | C
4 | 0 | D
How can I achieve this? Any help would be appreciated. Thank you!
I think that RIGHT JOIN will not work, since there are conditions in WHERE.
Try this:
SELECT
c.accountnumber,
COALESCE(SUM(a.totalsales),0) AS Amount,
c.companyname
FROM Accounts c
LEFT OUTER JOIN Sales a
ON a.Accountnumber = c.Accountnumber
AND a.Salesdate BETWEEN '1/1/2016' AND '1/27/2016'
WHERE
c.Accountnumber IN ('1', '2', '3', '4')
GROUP BY c.Accountnumber, c.companyname
Just to clarify, the problem is not which JOIN is used, it can be either, but using WHERE condition ON non-existing (NULL) values, since all not matched values from outer joined table are NULL anyway, any condition applied, practically make those joins inner joins (unless they are IS NULL conditions), see: http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
You should have two options.
Modify the query to select from the Accounts table first and then join the Sales table afterwards.
FROM Accounts c
LEFT OUTER JOIN Sales a on (a.Accountnumber = c.Accountnumber)
Use a RIGHT join instead of a LEFT one.
FROM Sales a
RIGHT OUTER JOIN Accounts c on (a.Accountnumber = c.Accountnumber)
Change it to a RIGHT OUTER JOIN and it should work.
A left join says keep everything in the left table, IE the table before the left join, even if it doesn't exist in the second table. In your case I sure hope there aren't any sales that don't have accounts. To keep all the Accounts even if they don't have a sale you need a RIGHT outer join. Alternatively you could change the order of the tables and do FROM Accounts c LEFT OUTER JOIN Sales a ...
Edit..
Blind got it. RIGHT OUTER JOIN is what you need to use given the way you wrote it but then you have a null for all the values in the columns from the sales table for 2 and 4 so the account number can't be in (1,2,3,4) or between the dates so they don't make it into the results.

Left Join with conditional on Right Table

I'm having trouble figuring out the sql for the following problem of mine. I have two tables like this:
+----------+------------+------------+
| event_id | event_name | event_date |
+----------+------------+------------+
+---------------+----------+---------+--------+
| attendance_id | event_id | user_id | status |
+---------------+----------+---------+--------+
What I am trying to do is to get a table like this:
+----------+--------+
| event_id | status |
+----------+--------+
Where the conditional for the second attendance table is the user_id. I'm trying to get a list of all the events as well as the status of a user for each one of those events, even if there is no record inside attendance (NULL is ok for now). And again, the status data from the attendance table needs to be chosen by the user_id.
From my initial research, I thought this would work:
SELECT event_id, status FROM events LEFT JOIN attendance WHERE attendance.user_id='someoutsideinput' ORDER BY event_date ASC
But that is not working for me as expected..how should I go about this?
Thanks!
all you need to do is to move the condition in the WHERE clause into ON clause.
SELECT events.event_id, COALESCE(attendance.status, 0) status
FROM events LEFT JOIN attendance
ON events.event_id = attendance.event_id AND
attendance.user_id='someoutsideinput'
ORDER BY events.event_date ASC
You need to more that condition to the JOIN clause instead of the WHERE clause.
BTW, you have not specified the join criteria between the tables, I have also corrected that below.
SELECT E.event_id
,A.status
FROM events E
LEFT JOIN
attendance A
ON E.event_id = A.event_id
AND A.user_id='someoutsideinput'
ORDER BY
E.event_date ASC

In MySQL, how can I get an aggregate function to return 0 after a where clause and a group by?

I have a table of users and a table of time-entries. I am trying to obtain the sum(time_entry.hours_worked) per employee where the date is within a range of values.
With:
SELECT employee.id, COALESCE(SUM(time_entry.hours_worked),0) as `sum`
FROM employee
LEFT JOIN time_entry
ON employee.id = time_entry.student_id
GROUP BY employee.id;
I am able to obtain entries for all employees, even if no hours are worked :
+----+--------+
| id | sum |
+----+--------+
| 1 | 191.00 |
| 2 | 48.00 |
| 3 | 0.00 |
+----+--------+
With a where statement:
SELECT employee.id, COALESCE(SUM(time_entry.hours_worked),0) AS `sum`
FROM employee
LEFT JOIN time_entry
ON employee.id = time_entry.student_id
WHERE time_entry.date < 1367798400
GROUP BY employee.id;
I obtain an empty set. How can I use the WHERE statement and still obtain 0 per employee when no entries are found in the database?
The problem is that the condition is on the second table in the left outer join. When there is no match, all the columns are set to NULL. So, the where clause fails. In fact, such a condition is turning the left outer join back into an inner join.
To fix this, move the condition to the on clause:
SELECT employee.id, COALESCE(SUM(time_entry.hours_worked),0) AS `sum`
FROM employee
LEFT JOIN time_entry
ON employee.id = time_entry.student_id and
time_entry.date < 1367798400
GROUP BY employee.id;

Setting a default value on NULL columns from LEFT JOIN and filtering using WHERE

I have a table of items and I have a separate table containing the individual purchases of each item. Not every item has been purchased. I am selecting the purchase count and joining it with the items table with a statement similar to the following:
SELECT items.name, purchases_count
FROM `items`
LEFT JOIN (SELECT sales.item_name, SUM(unit_sales) AS purchases_count
FROM sales GROUP BY item_name) sales ON sales.item_name = items.uid
This results in data similar to:
+------+-----------------+
| name | purchases_count |
|------+-----------------+
| Shoe | 12 |
| Belt | NULL |
+------+-----------------+
My problem arises when I want to filter this result on the purchases_count. If I use WHERE purchases_count < 10 or something similar, items with no sales record at all (i.e. those with a NULL value) are excluded from the search.
I have attempted to use COALESCE(purchases_count,0) AS purchases_count which does correctly set NULL records to 0, but they are still not appearing when using WHERE. I suspect the COALESCE is happening after the WHERE.
I would like to be able to filter on this number using WHERE and include NULL results (as zeros) if possible. Any suggestions?
Aliases don't generally apply in the WHERE clause - try COALESCE(purchases_count,0) AS purchases_count_2 with where purchases_count_2 < 10 to see what I mean.
where COALESCE(purchases_count,0) < 10 should work.
Instead of counting the purchases in a separate query, just group the main query instead. To filter on the count, put that in a having caluse:
select i.name, coalesce(sum(s.unit_sales), 0) as purchases_count
from items i
left join sales s on s.item_name = i.uid
group by i.name
having purchases_count < 10
How about:
WHERE (purchases_count < 10) OR (purchases_count IS NULL)
of course, you'd still be left with null values, but you can still try the COALESCE option to turn those nulls into zeroes for later usage.
have u try this
SELECT items.name, IFNULL(purchases_count,0)
FROM `items`
LEFT JOIN (
SELECT item_name, SUM(unit_sales) AS purchases_count
FROM sales GROUP BY item_name
) s ON s.item_name = items.uid
GROUP BY items.name
HAVING purchases_count >10
COALESCE is correct way, but you should not use WHERE, try :-
HAVING purchases_count<=10
So, you can add a where clause like this:
WHERE purchases_count < 10 OR purchases_count is NULL