Mysql group by day - mysql

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

Related

Mysql group by dates in weekends

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);

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: get daily average price of product table with version

my products table :
ProductId(inc.key) | Price | VersionCreatedDate | MainProductId
1 | 15 | 1-11-2016 | 1
2 | 20 | 1-11-2016 | 2
3 | 30 | 1-11-2016 | 3
4 | 10 | 2-11-2016 | 1 -> mainProductId 1 changed price(-5$)
5 | 20 | 3-11-2016 | 3 -> mainProductId 3 changed price(-10$)
6 | 30 | 4-11-2016 | 3 -> mainProductId 3 changed price(+10$)
I want to display the output as like this
Date | AvgPrice
1-11-2016 | 21.67 ((15+20+30)/3)
2-11-2016 | 20 ((10+20+30)/3)
3-11-2016 | 16.67 ((10+20+20)/3)
4-11-2016 | 20 ((10+20+30)/3)
How do I get the output with sql code?
Assuming you have a calendar table with all dates you need. And you have a main_products table with MainProductId as primary/unique key. The following query should return average prices for every day in october 2016.
select sub.date, avg(sub.Price) as Price
from (
select
c.date,
m.MainProductId,
(
select p.Price
from products
where p.MainProductId = m.MainProductId
and p.VersionCreatedDate < c.date + interval 1 day
order by p.VersionCreatedDate desc
limit 1
) as Price
from callendar c
cross join main_products m
where c.date between '2016-10-01' and '2016-10-31'
) sub
group by sub.date
order by sub.date
The subquery (derived table aliased as sub) returns a combination of all dates in the range and all "main products" from the main_products table. The recent price each "main product" for a specific date is calculated in the subselect (correlated subquery in the SELECT clause) using ORDER BY and LIMIT 1. This allows us to group the subquery result by date and calculate the average price per date.
It is even possible to eliminate the derived table and hope that mysql can use an index to GROUP BY date instead of working on a temp table:
select c.date, avg((
select p.Price
from products
where p.MainProductId = m.MainProductId
and p.VersionCreatedDate < c.date + interval 1 day
order by p.VersionCreatedDate desc
limit 1
)) as Price
from callendar c
cross join main_products m
where c.date between '2016-10-01' and '2016-10-31'
group by c.date
order by c.date
I have no clue if that query can be executed effiently (especially if mysql can). You should however have at least the following indexes: callendar(date), products(MainProductId, VersionCreatedDate)

SQL query to check if column includes some data

I need to select all free rooms from hotel DB and I think I can do it with two steps:
bookings = select * from booking where booking.startDate>=selectedStartDate and booking.endDate=<selectedEndDate.
pseudo query: select * from room where room.room_id not includes bookings.room_id.
I wrote my second query like pseudo query because I can't find how I can do what I want to do. How to check that bookings doesn't includes room_id's?
My booking table looks like:
+-----------+------------+------------+---------+---------+
| bookingId | startDate | endDate | room_id | guestId |
+-----------+------------+------------+---------+---------+
| 1 | 2016-03-12 | 2016-03-22 | 1 | 1 |
| 2 | 2016-03-12 | 2016-03-22 | 2 | 2 |
+-----------+------------+------------+---------+---------+
You could transform the first query to a subquery of the second query by using the not in operator:
SELECT *
FROM room
WHERE room.room_id NOT IN (SELECT room_id
FROM booking
WHERE startDate >= selectedEndDate AND
endDate <= selectedStartDate)
If you want rooms free during a period of time, use not exists. The correct logic is:
select r.*
from room r
where not exists (select 1
from booking b
where $startdate <= b.enddate and $enddate >= b.startdate
);
Two periods overlap when one starts before the second ends and the first ends after the second starts.
Note that the <= and >= might be strict inequalities, depending on whether the first and last dates are included in the period.
You can use a more optimized query
SELECT * FROM room JOIN booking ON room.room_id = booking.room_id
WHERE booking.startDate >= selectedStartDate AND booking.endDate <= selectedEndDate

sql query for each day

i have a table main:
(
time date,
qty int
)
i want to create a query so for each day i get the sum of qty on that day and all days before that
so for this data
-----------------------
time | qty
01/09/2009 | 3
02/09/2009 | 8
03/09/2009 | 2
04/09/2009 | 5
i get:
-----------------------
time | total
01/09/2009 | 3
02/09/2009 | 11
03/09/2009 | 13
04/09/2009 | 18
thanks in advance
This should give you a faster result
SELECT time
, #tot_qty := #tot_qty+qty AS tot_qty
FROM Table1
JOIN (SELECT #tot_qty := 0) d
order by time
SQL FIDDLE
SELECT
M.Time,
SUM(M2.Qty) RunningTotal
FROM
Main M
LEFT JOIN Main M2 ON M.Time >= M2.Time
GROUP BY
M.Time;
SELECT TIME, (SELECT SUM(QTY) FROM main m2 WHERE m2.ITME <= mt1.TIME) AS sum
FROM main m1
ORDER BY TIME
This should do the trick, though it might not be the fastest solution.