Mysql group by dates in weekends - mysql

I have the next database:
What I want to get is the name of the city, and the number of tours grouped by weekends
I was trying to do something like this
select `cities`.`name`,
SUM( CASE DAYOFWEEK(DATE(date)) WHEN 7 OR 1 THEN 1 ELSE 0 END)AS TOURS
from `cities`
left join `tours` on `cities`.`id` = `tours`.`city_id`
group by `cities`.`name`;
So if I have tours on the dates 2019/03/02 (Saturday), 2019/03/03 (Sunday) in the city X I would return X and 1 tour, as it groups the dates by the weekend. and if it had the dates 2019/03/09, 2019/03/10, I would return the Name of city X and 2 tours, since it has the dates of 2 and 3 as 1; and 9 and 10 as another tour.
the query I did only counts on Saturday and Sunday without distinguishing between different weeks.
Any idea?
UPDATE
I have added a fiddle
Fiddle
The desired result is
| name | TOURS |
| ----------- | ----- |
| Amatitlan | 0 |
| Guatemala | 3 |
| Villa Nueva | 1 |

I Added
count(distinct week(`tours`.`date`, 1))AS TOURS
And complete query
select `cities`.`name`,
count(distinct week(`tours`.`date`, 1))AS TOURS
from `cities`
left join `tours` on `cities`.`id` = `tours`.`city_id`
group by `cities`.`name`;
fiddle with the desired result

if i understand correctly you want your count of tour by different weeks only for weekend.
I think below is solution. correct me if i am wrong.
select `cities`.`name`,
SUM( CASE DAYOFWEEK(DATE(date)) WHEN 7 OR 1 THEN 1 ELSE 0 END)AS TOURS,
WEEKS(date),
from `cities`
left join `tours` on `cities`.`id` = `tours`.`city_id`
group by `cities`.`name`,WEEKS(date);

Related

Combine results from 3 sql queries to calculate running stock

I am trying to calculate the stock by product a warehouse had over time. I have the information about today's stock, and also the amount of products sold and purchased by day. So, the calculation for yesterday values would be:
Yesterday_stock=Stock-yesterday_sold_quantity+yesterday_purchased_quantity. My problem is that i should save somewhere the amount of everyday's stock in order to calculate the stock of the previous day. I found that in order to do that i could use over sql clause with order by. But unfortunately, i have sql server 2008 and this is not a choice.
The tables are:
Prdamount which holds the current stock per product (StuPrdID ) and if it is blocked for some reason.
|-------------- |------------------|---------------
| StuPrdID | StuQAmount |prdBlockingReason
|---------------|------------------|-------------
| 12345| 16 |
|---------------|------------------|--------------
| 08889| 12 | expired
|---------------|------------------|------------
Table Moves which holds information about inserts and outputs of products. If MoveCase field has value equal 1 it is an output move, if it is a 2 it is a purchased quantity. Moves table dummy data:
|-------------- |--------------------- -|--------|-------
|MoveItemCode | MoveDate |MoveCase|MoveRealQty
|---------------|---------------------- |--------|-------
| 12345 |2018-06-24 00:00:00.000| 1 |14
|---------------|-----------------------|--------|--------
| 08889 |2018-06-24 00:00:00.000| 2 |578
|---------------|-----------------------|--------|--------
and table Product with information related with data:
|-------------- |------------------|
| PrdCode | PrdDespription |
|---------------|------------------|
| 12345| Orange juice|
|---------------|------------------|
| 08889| Chocolate|
|---------------|------------------|
I want an output like this:
|------------|--------------------- -|--------|--------------|------------
|Prdcode | PrdDescription |Stock |Stock 18/07/03|Stock 18/7/02
|------------|---------------------- |--------|--------------|------------
| 12345 |Orange Juice | 80 |50 34
|----------- |-----------------------|--------|--------------|------------
| 08889 |Chocolate | 45 |82 17
|------------|-----------------------|--------|--------------|-------------
this query gives me the running stock:
select
product.PrdCode,
product.PrdDescr,
SUM(StuQAmount) as Stock
from prdamount
left join product on (product.PrdID=prdamount.StuPrdID)
where prdamount.prdBlockingReason=' '
group by product.PrdCode,product.PrdDescr
order by product.PrdCode asc
This query gives me the quantity sold by product per day:
select
moves.MoveItemCode,
prd.PrdDescr,
moves.MoveDate,
SUM(MoveRealQty) as 'sold_quantity'
from moves
left join prd on (moves.MoveItemCode=product.PrdCode)
where (moves.MoveDate>'2018-06-01' and and moves.MoveCase=1)
group by moves.MoveItemCode,product.PrdDescr,moves.MoveDate
order by moves.MoveItemCode asc,moves.MoveDate asc
And this query gives me the quantity purchases by product per day:
select
moves.MoveItemCode,
prd.PrdDescr,
moves.MoveDate,
SUM(MoveRealQty) as 'Purchased_Quantity'
from Moves
left join product on (moves.MoveItemCode=product.PrdCode)
where (moves.MoveDate>'2018-06-01' and moves.MoveCase=2)
group by moves.MoveItemCode,product.PrdDescr,moves.MoveDate
order by moves.MoveItemCode asc,moves.MoveDate asc
I tried to combine these 3 queries into one using subqueries, but it didn't work. So how can i accomplish the result that i want? Sorry if the question is silly, i am a beginner in sql
try this,
select
product.PrdCode,
moves.MoveItemCode,
product.PrdDescr,
moves.MoveDate,
SUM( case when moves.MoveCase=1 then MoveRealQty else 0 end) as 'sold_quantity',
SUM( case when moves.MoveCase=2 then MoveRealQty else 0 end) as 'Purchased_Quantity',
(select SUM(StuQAmount) from prdamount where StuPrdID = product.PrdID and prdBlockingReason=' ')
from moves
left join product on (moves.MoveItemCode=product.PrdCode)
where (moves.MoveDate>'2018-06-01')
group by moves.MoveItemCode,product.PrdDescr,moves.MoveDate, product.PrdCode
order by moves.MoveItemCode asc,moves.MoveDate asc

Mysql group by day

This is my tables :
car_event
id
start_date
employee_car_event
car_event_id
employee_id
Some employees works two time on one day.
In my exemple employee 1 and 2 work the same day two time.
I want to know how many days works each employees
I try to do :
select
count(employee_car_event.id) as nbrJour,
employee_car_event.employee_id as idEmployee,
DATE_FORMAT(car_event.startDate, '%Y%m%d') as gday
from employee_car_event
left join
car_event on car_event.id = employee_car_event.car_event_id
group by gday, employee_car_event.employee_id
But i have this :
2 | 1 | 20170320
2 | 2 | 20170320
And i want :
1 | 1 | 20170320
1 | 2 | 20170320
Thank's a lot for your help
try with this query
select
count(distinct employee_car_event.employee_id) as nbrJour,
employee_car_event.employee_id as idEmployee,
DATE_FORMAT(car_event.startDate, '%Y%m%d') as gday
from employee_car_event
left join
car_event on car_event.id = employee_car_event.car_event_id
group by gday, employee_car_event.employee_id

MySQL duplicate entries search with selective date criteria

Having trouble wrapping my head around having an efficient "duplicate entries" select in a single query.
In the below example, duplicate StockNo can exist spanning multiple Date. I want to search StockNo for duplicate entries, and if at least 1 StockNo record is found within the Date current YEAR-MONTH, then I also need to select its partner that could exist in any other YEAR-MONTH. Is this possible?
Example Query:
SELECT * FROM `sales`
WHERE `StockNo` IN
(SELECT `StockNo` FROM `sales` GROUP BY `StockNo` HAVING COUNT(*) > 1)
AND `Date` LIKE '2016-11-%'
ORDER BY `StockNo`, `TransactionID`;
Example Data:
ID | StockNo | Date
1 | 1 | 2016-11-01
2 | 1 | 2016-11-10
3 | 2 | 2016-11-05
4 | 2 | 2016-10-29
5 | 3 | 2016-10-25
6 | 3 | 2016-10-15
With my example query and data, I have 3 pairs of duplicate entries. It's pretty obvious that I will only return 3 records (ID's 1, 2 & 3) due to AND Date LIKE '2016-11-%', however I need to return ID's 1, 2, 3, 4. I want to ignore ID's 5 & 6 because neither of them fall within the current month.
Hope that makes sense. Thanks for any help you can provide.
SELECT StockNo
FROM sales
GROUP BY StockNo
HAVING SUM(CASE WHEN DATE_FORMAT(Date, '%Y-%m') = '2016-11' THEN 1 ELSE 0 END) > 0
If you also want to retrieve the full records for those matching stock numbers in the above query, you can just add a join:
SELECT s1.*
FROM sales s1
INNER JOIN
(
SELECT StockNo
FROM sales
GROUP BY StockNo
HAVING SUM(CASE WHEN DATE_FORMAT(Date, '%Y-%m') = '2016-11' THEN 1 ELSE 0 END) > 0
) s2
ON s1.StockNo = s2.StockNo
Demo here:
SQLFiddle
Thank you very much Tim for pointing me in the right direction. Your answer was close but it still only returned records from the current month and in the end I used the following query:
SELECT s1.* FROM `sales` s1
INNER JOIN
(
SELECT * FROM `sales` GROUP BY `StockNo` HAVING COUNT(`StockNo`) > 1
AND SUM(CASE WHEN DATE_FORMAT(`Date`, '%Y-%m')='2016-11' THEN 1 ELSE 0 END) > 0
) s2
ON s1.StockNo=s2.StockNo
This one had been eluding me for some time.

Retrieving data from two different tables with common column using left outer join and on clause

Guys I have two different tables.
Table-1:
contract-id | contract-date
1 | 01-05-2016
1 | 01-06-2016
1 | 01-07-2016
2 | 01-01-2016
2 | 01-02-2016
3 | 01-05-2016
3 | 01-06-2016
Table-2:
invoice-number|contract-id|invoice-from-date|invoice-to-date
1 |1 |01-05-2016 |31-05-2016
2 |1 |15-05-2016 |31-05-2016
3 |1 |25-05-2016 |31-05-2016
My requirement is, I have to show what are all the contracts that comes in the current month from table-1 and I have to show the count of the invoice raised for those contracts from table-2. If there are any invoice raised, it should show its count or simply zero. The expected answer is:
contract-id|counts
1 |3
3 |0
The count for contract-id: 1 is 3, because I've raised three invoices for the current month and the count for contract-id: 3 is 0, because I haven't raised any invoice for it. And contract-id:2 is missing , because, it does not come under current month.
This is what I've tried:
select cbm_contract_period_value_split.contract_id,
count(cbm_contract_invoice_request.contract_id),
cbm_contract_period_value_split.contract_date
from cbm_contract_period_value_split
left outer join cbm_contract_invoice_request
on cbm_contract_period_value_split.contract_id = cbm_contract_invoice_request.contract_id
and MONTH(cbm_contract_period_value_split.contract_date) = MONTH(CURDATE())
and MONTH(cbm_contract_invoice_request.invoice_for_the_period_of_from_date) = MONTH(CURDATE())
I've already posted this question, but now I'm posting this with an edited version with the answers I got. Yet, I'm not getting the desired answer. What's wrong and what should I do?
try this one. I think you need a GROUP BY and I put in the WHERE to filter out the rows that aren't current month.
select pvs.contract_id,
count(ir.contract_id) as counts,
pvs.contract_date
from cbm_contract_period_value_split as pvs
left join cbm_contract_invoice_request as ir
on pvs.contract_id = ir.contract_id
and MONTH(ir.invoice_for_the_period_of_from_date) = MONTH(CURDATE())
WHERE MONTH(pvs.contract_date) = MONTH(CURDATE())
GROUP BY pvs.contract_id,pvs.contract_date
http://sqlfiddle.com/#!9/e5f08c/9
result
contract_id counts contract_date
1 3 May, 01 2016 00:00:00
3 0 May, 01 2016 00:00:00
Try this query..
SELECT
t1.`contract-id`,
(
CASE
WHEN t2.`contract-id` IS NULL
THEN 0
ELSE COUNT(*)
END
) AS counts
FROM
t1
LEFT JOIN t2
ON t1.`contract-id` = t2.`contract-id`
WHERE MONTH(`contract-date`) = MONTH(CURDATE())
GROUP BY t2.`contract-id`
ORDER BY t1.`contract-id`,`contract-date` ;
FIDDLE
SELECT Table-1.contract_id, Table-1.contract-date, COUNT(*) AS count FROM Table-2 LEFT JOIN Table-1 ON Table-1.contract_id = Table-2.contract_id WHERE MONTH(Table-1.contract-date) = MONTH(CURDATE()) GROUP BY Table-1.contract_id

select particular items ordered n times

i have two tables, one invoice and the other the details where i need to select products ordered n times by a particular customer within a date range
the tables in part looks like this
Invoice
invid | custid | invdate
----------------------------
101 | 11 | 2014-2-10
102 | 22 | 2014-2-15
103 | 22 | 2014-3-01
104 | 11 | 2014-3-14
Details
invid | item
------------
101 | bread
102 | bread
103 | chips
104 | chips
102 | bread
103 | bread
104 | chips
101 | bread
from the code above, i need to select say all customers who ordered the same items 2 times or more within 2014-2-10 and 2014-3-09, excluding any customer who purchased the same item in the week 2014-3-10 to 2014-3-14
for example
if customer orders bread 2 times between date1 and date2 and did not order the same bread between date3 and date4 then it should be in the output
and date the expected output should be
custid | item | item_count
22 | bread | 2
the custid 11 would have NOT fit the list, because they also purchased in the week 2014-3-10 to 2014-3-14, but it they did not purchased the same item in the passed dates
this is what i tried
SELECT
i.custid, d.ITEM,COUNT(d.ITEM) as orders
From `details` d
LEFT JOIN `invoices` i on i.invid= d.invid
WHERE
i.invdate >= '2014-2-10' AND
i.invdate <= '2014-3-14' AND
i.custid NOT IN
(SELECT custid FROM `invoices` WHERE invdate >= '2014-3-10')
Group By i.invid, d.ITEM
HAVING COUNT(d.ITEM) >= 2
when i run again the full table, i get 1 item instead of 6. I did manually using excel through a number of functions to be sure, in this case none
Typical MySQL error. You mistakenly group by invid instead of custid.
SELECT
i.custid, d.ITEM, COUNT(d.ITEM) as orders
From `details` d
LEFT JOIN `invoices` i on i.invid= d.invid
WHERE
i.invdate >= '2014-2-10' AND
i.invdate <= '2014-3-14' AND
i.custid NOT IN
(SELECT custid FROM `invoices` WHERE invdate >= '2014-3-10')
Group By i.custid, d.ITEM
HAVING COUNT(d.ITEM) >= 2;
EDIT: Okay, here is a closer look at it.
Correct the GROUP BY as already mentioned.
You outer join invoices although there should be no details record without an invoices record. Change this to INNER JOIN.
You are confusing dates. The purchase date shall be between '2014-2-10' and '2014-3-09' and must not be between '2014-3-10' to '2014-3-14'
Then: You don't want to exclude customers who bought something in that latter week. You want to exclude customer-item combinations that occured then.
My suggestion: select from both date ranges and check then if all macthes for a customer-item combination are within the desired week and still have a count of at least two:
select
i.custid,
d.item,
count(d.item) as orders
from invoices i
inner join details d on d.invid = i.invid
where i.invdate between '2014-2-10' and '2014-3-09'
or i.invdate between '2014-3-10' and '2014-3-14'
group by i.custid, d.item
having count(*) >= 2 and max(i.invdate) between '2014-2-10' and '2014-3-09;
SELECT i1.custid, d1.ITEM, COUNT(*) orders
FROM (invoices i1 JOIN details d1 USING (invid))
LEFT JOIN (invoices i2 JOIN details d2 USING (invid))
ON i2.custid = i1.custid
AND d2.ITEM = d1.ITEM
AND i2.invdate BETWEEN '2014-03-10' AND '2014-03-14'
WHERE i1.invdate BETWEEN '2014-02-10' AND '2014-03-09'
AND i2.custid IS NULL
GROUP BY i1.custid, d1.ITEM
HAVING orders >= 2
See it on sqlfiddle.