Get products without sales for last 7day - mysql

I have two tables products and user_sales. I need to get the products which have 0 sales for the last 7 days.
I tried some code which I found in stack overflow with the "HAVING" statement but I found out if I put a limit of 12 products than it doesnt works.
Can anoyone please help ?
table products
id | title | price | images | description
table user_sales
id | product_id | sale_date | user_owner
Well that was the simplified version of the tables. The actual query looks somehow like this.
SELECT `product_store`.`friendly_name` AS `store_friendly_name`,
`api_keys`.`key_data` AS `api_data`,
`ep`.*,
`supplier_store`.`icon` AS `supplier_store_icon`,
`supplier_store`.`internal_name` AS `supplier_store_internal_name`,
`supplier_store`.`friendly_name` AS `supplier_store_friendly_name`,
`supplier_store`.`amazon_type_product` AS
`supplier_store_amazon_type_product`,
`supplier_store`.`handler` AS `supplier_store_handler`,
`sp`.`extra_data` AS `sp_extra_data`,
`sp`.`id` AS `sp_id`,
`sp`.`remote_id` AS `sp_remote_id`,
`sp`.`url` AS `sp_url`,
`sp`.`price` AS `sp_price`,
`sp`.`stock` AS `sp_stock`,
`sp`.`picture` AS `sp_picture`,
`sp`.`store_id` AS `sp_store_id`,
Count(us.date) AS sale_date
FROM `products` `ep`
LEFT JOIN `stores` `product_store`
ON `ep`.`store_id` = `product_store`.`id`
LEFT JOIN `api_keys`
ON `api_keys`.`id` = `ep`.`link_key`
LEFT JOIN `products` `sp`
ON `ep`.`linked_to` = `sp`.`id`
LEFT JOIN `stores` `supplier_store`
ON `supplier_store`.`id` = `sp`.`store_id`
RIGHT JOIN `user_sales` `us`
ON `ep`.`remote_id` = `us`.`remote_id`
WHERE `ep`.`user_owner` = '3992'
AND `ep`.`expired` = 0
AND `us`.`user_id` = '3992'
AND us.date > "2019-02-09 14:21:34"
AND us.date < "2019-05-10 14:21:34"
AND `ep`.`store_id` = 3
GROUP BY `ep`.`id`
HAVING `sale_date` < 1
ORDER BY `ep`.`id` DESC
LIMIT 15

You want to ensure that no sales exist for the product in the last seven days. Use NOT EXISTS for that.
From your query I take it that you want to restrict this to products belonging to user_owner 3992 and to sales of the same user.
WHERE ep.user_owner = 3992
AND ep.expired = 0
AND ep.store_id = 3
AND NOT EXISTS
(
SELECT *
FROM user_sales us
WHERE us.user_id = ep.user_owner
AND us.date > current_date - interval 7 day
)
The complete query:
SELECT product_store.friendly_name AS store_friendly_name,
api_keys.key_data AS api_data,
ep.*,
supplier_store.icon AS supplier_store_icon,
supplier_store.internal_name AS supplier_store_internal_name,
supplier_store.friendly_name AS supplier_store_friendly_name,
supplier_store.amazon_type_product AS
supplier_store_amazon_type_product,
supplier_store.handler AS supplier_store_handler,
sp.extra_data AS sp_extra_data,
sp.id AS sp_id,
sp.remote_id AS sp_remote_id,
sp.url AS sp_url,
sp.price AS sp_price,
sp.stock AS sp_stock,
sp.picture AS sp_picture,
sp.store_id AS sp_store_id
FROM products ep
LEFT JOIN stores product_store ON ep.store_id = product_store.id
LEFT JOIN api_keys ON api_keys.id = ep.link_key
LEFT JOIN products sp ON ep.linked_to = sp.id
LEFT JOIN stores supplier_store ON supplier_store.id = sp.store_id
WHERE ep.user_owner = 3992
AND ep.expired = 0
AND ep.store_id = 3
AND NOT EXISTS
(
SELECT *
FROM user_sales us
WHERE us.user_id = ep.user_owner
AND us.date > current_date - interval 7 day
)
ORDER BY ep.id DESC;

Related

Mysql return value with nested Select

I am writing some software for a restaurant. They change prices on certain dates. I have two tables, one with the products ordered by order, and another with prices, historical, that is, every time they change a price, I set a bit to 0 to the old value, create new entry and assign bit 1 into "valid" column.
I use the following MySQL code to recall the valid actual price:
`
SELECT
`tbl_precios_productos`.`dbl_precio`
FROM `tbl_precios_productos`
left join `tbl_prods_x_orden` on `tbl_prods_x_orden`.`int_producto_id` = `tbl_precios_productos`.`id_producto`
where `tbl_prods_x_orden`.`int_producto_id` = `tbl_precios_productos`.`id_producto`
and `tbl_precios_productos`.`bit_activo` = 1
And `tbl_precios_productos`.`int_tipo_precio` = 1
and `tbl_prods_x_orden`.`int_producto_id` = 10 /* this is the ID of the product */
GROUP BY `tbl_precios_productos`.`dbl_precio`
`
When I try to nest that code into a bigger one, it doesn't work. Here is what I tried:
`
SELECT
ANY_VALUE( `tbl_productos`.`id_producto`) AS `ID Prod`,
ANY_VALUE( `tbl_productos`.`chr_nombre_prod`) AS `Producto`,
SUM(ANY_VALUE( `tbl_prods_x_orden`.`int_cantidad`)) AS `Cantidad`,
(SELECT
`tbl_precios_productos`.`dbl_precio`
FROM `tbl_precios_productos`
left join `tbl_prods_x_orden` on `tbl_prods_x_orden`.`int_producto_id` = `tbl_precios_productos`.`id_producto`
where `tbl_prods_x_orden`.`int_producto_id` = `tbl_precios_productos`.`id_producto`
and `tbl_precios_productos`.`bit_activo` = 1
And `tbl_precios_productos`.`int_tipo_precio` = 1
and `tbl_prods_x_orden`.`int_producto_id` = `tbl_precios_productos`.`id_producto`
GROUP BY `tbl_precios_productos`.`dbl_precio`) AS `Precio`,
ANY_VALUE( `tbl_tipos_precios`.`id_tipo_precio`) AS `Tipo Precio`,
ANY_VALUE( `tbl_tipos_precios`.`chr_nombre_precio`) AS `CHRTipoPrecio`,
ANY_VALUE( `tbl_ordenes_cerradas`.`int_forma_pago`) AS `ID TPago`,
ANY_VALUE( `tbl_formas_pago`.`chr_forma_pago`) AS `Tipo Pago`,
ANY_VALUE( `tbl_productos`.`fl_ordenar`) AS `Ordenar`
From `tbl_prods_x_orden`
LEFT JOIN `tbl_productos` ON `tbl_prods_x_orden`.`int_producto_id` = `tbl_productos`.`id_producto`
LEFT JOIN `tbl_precios_productos` ON (((`tbl_prods_x_orden`.`int_producto_id` = `tbl_precios_productos`.`id_producto`) And ( `tbl_precios_productos`.`int_tipo_precio` = 1)))
LEFT JOIN `tbl_precio_tipo_ordenes` ON `tbl_prods_x_orden`.`int_orden_id` = `tbl_precio_tipo_ordenes`.`id_orden`
LEFT JOIN `tbl_tipos_precios` ON `tbl_tipos_precios`.`id_tipo_precio` = `tbl_precio_tipo_ordenes`.`id_tipo_precio`
LEFT JOIN `tbl_ordenes_cerradas` ON `tbl_ordenes_cerradas`.`id_orden_id` = `tbl_prods_x_orden`.`int_orden_id`
left join `tbl_formas_pago` ON `tbl_ordenes_cerradas`.`int_forma_pago` = `tbl_formas_pago`.`id_forma_pago`
WHERE `tbl_productos`.`int_activo` = 1
And `tbl_prods_x_orden`.`bool_activo` = '1'
and `tbl_ordenes_cerradas`.`int_forma_pago` = 3
And `tbl_ordenes_cerradas`.`id_control_fecha` >= 101
And `tbl_ordenes_cerradas`.`id_control_fecha` <= 101
group BY `ID Prod`, `Tipo Precio`, `ID TPago`
order by `Ordenar`
`
I get an error that the subquery returns more than one result. How can I get the specific valid price from the prices table using the id of the product. Imagine prices table with 4 columns: id, id_producto, valid, date_set. Sorry some of the code is in spanish, that is my mother language and what I am using to program, but I hope you get the idea.
Am I doing it correctly or is there any other way?
Thanks in advance.

Complex subqueries wihtin CASE statement

I have this query that calculates the expected value of a receipt, based on the 'channel' of acquisition of the user, on the 'id_store' and on the 'country' of the user.
The resulting query has this columns.
Count | id_store | country | price_usd | channel | T2S | ExpectedRevenue | ExpectedRevenue_projections
(note: ExpectedRevenue = count * price_usd * T2S)
In this query I want to know the value of those receipts that where purchased on August and expire on September (these products have a trial period, and we calculate their value is based on the historical conversion rate (Trial 2 subscription a.k.a. T2S)).
The problem arises when we do not have historical data for some scenarios; either we started selling different with id_stores, new country, channel, or any combination of the previous ones and the T2S becomes as a 'null' value and column 'ExpectedRevenue' therefore has 'null' values' ---> That is why I have a 'CASE' function that makes T2S to take the value of '.28' whenever this happens and I only have to sum the column 'ExpectedRevenue_projections' in order to get the final result.
However, this '.28' is just a fixed value that is not accurate at all (we have products from 10 to 120$...).
That's why I'm asking dear stackoverflow contributors is to replace this '28%' for another T2S that in this case would be calculated historically according to 'country' and 'price_usd' intervals such as (0-15), (15.01-29.99), (30 - 49.99)... and so on.
(The reason to put intervals is that 'price_usd' is calculated based on the exchange rate at the moment of the creation so the same product purchase by a customer in foreign currency could be 49.99, 49.98 , 49.97... and T2S would come as 'null' if there is not historical data).
Thank you
SELECT
r.count AS count,
r.id_store AS id_store,
r.country AS country,
r.price_usd AS price_usd,
r.channel AS channel,
a.count / (a.count + u.count) AS T2S,
r.count * r.price_usd * (a.count / (a.count + u.count)) AS ExpectedRevenue,
CASE WHEN (a.count / (a.count + u.count)) is null then (r.count * r.price_usd * .28) else r.count * r.price_usd * (a.count / (a.count + u.count)) END AS ExpectedRevenue_projections
FROM
(
select count(distinct(r.user_id)) AS count, p.id_store, u.country, r.price_usd, channel
from receipts as r
inner join products as p on p.id=r.product_id
inner join customers as c on r.customer_id=c.id
inner join users as u on u.id=r.user_id
where
MONTH(DATE_ADD(DATE_ADD(r.original_subscription_at, INTERVAL p.trial_days DAY), INTERVAL p.trial_months MONTH)) = 9
and YEAR(original_subscription_at) = 2017
and MONTH(original_subscription_at) = 8
and YEAR(r.expiration_at) = 2017
and MONTH(r.expiration_at) = 9
and r.status='trial'
and p.platform not in ('manual')
and c.tester=0
group by 2,3,4,5
) AS r
LEFT JOIN
(
select count(distinct r.user_id) AS count, u.country, p.id_store, channel
from receipts as r
inner join products as p on p.id=r.product_id
inner join users as u on u.id=r.user_id
where year(r.created_at)=2017
AND r.status = 'active'
group by 2,3,4
) AS a
ON r.country = a.country AND r.id_store = a.id_store AND r.channel = a.channel
LEFT JOIN
(
select count(distinct r.user_id) AS count, u.country, p.id_store, channel
from receipts as r
inner join products as p on p.id=r.product_id
inner join users as u on u.id=r.user_id
where year(r.created_at)=2017
AND r.status = 'unpaid'
group by 2,3,4
) AS u
ON r.country = u.country AND r.id_store = u.id_store AND r.channel = u.channel

GTFS get last stop on trip

Using a standard GTFS database, I'm trying to add the name of the last stop on a trip to my current query which returns the following:
| trip_id | service_id | departure_stop | departure_time | arrival_stop | arrival_time | end_departure |
|---------------------------------|------------|----------------|----------------|-----------------|--------------|---------------|
| 15693832.T6.2-EPP-E-mjp-1.11.R | T6_1 | Clifton Hill | 04:56:00 | Flinders Street | 05:07:00 | 05:07:00 |
and so on.
My current query is:
select `t`.`trip_id`,
`c`.`service_id`,
`start_s`.`stop_name` as `departure_stop`,
`start_st`.`departure_time`,
`end_s`.`stop_name` as `arrival_stop`,
`end_st`.`arrival_time`,
`end_st`.`departure_time` as `end_departure`
from `trips` as `t`
inner join `calendar` as `c` on `t`.`service_id` = `c`.`service_id`
inner join `routes` as `r` on `t`.`route_id` = `r`.`route_id`
inner join `stop_times` as `start_st` on `t`.`trip_id` = `start_st`.`trip_id`
inner join `stops` as `start_s` on `start_st`.`stop_id` = `start_s`.`stop_id`
inner join `stop_times` as `end_st` on `t`.`trip_id` = `end_st`.`trip_id`
inner join `stops` as `end_s` on `end_st`.`stop_id` = `end_s`.`stop_id`
where `start_st`.`departure_time` > '00:00:00'
and `start_st`.`departure_time` < '23:59:59'
and `start_s`.`stop_id` = 19974
and `end_s`.`stop_id` = 19854
and start_st.departure_time < end_st.arrival_time
order by arrival_time asc
I'm stuck trying to figure out how I can get the last stop in the stop_times table for the trip_id that my query returns for each row.
So in addition to what I have currently, I'd like to:
get the last stop_id for that trip_id in the stop_times table
get the stop_name from the stops table for the corresponding stop_id
display it as the last column in my output as last_stop
Update:
I've tried selecting s.stop_name and adding the following inner join:
inner join (
SELECT s.stop_name, trip_id
FROM stop_times
INNER JOIN stops as s on `s`.`stop_id` = `stop_times`.`stop_id`
ORDER BY stop_sequence DESC
) s on `t`.`trip_id` = `s`.`trip_id`
However, this adds extra rows for every single stop in trip, where I only want the last one and adding LIMIT 1 returns no results.
One caution, arrival and departure times may be later than midnight in the GTFS spec (hour value could be 24, 25, etc.)
select "t"."trip_id",
"c"."service_id",
"start_s"."stop_name" as "departure_stop",
"start_st"."departure_time",
"end_s"."stop_name" as "arrival_stop",
"end_st"."arrival_time",
"end_st"."departure_time" as "end_departure",
"last_st"."arrival_time" as "last_arrival",
"last_s"."stop_name" as "last_stop"
from "trips" as "t"
inner join "calendar" as "c" on "t"."service_id" = "c"."service_id"
inner join "routes" as "r" on "t"."route_id" = "r"."route_id"
inner join "stop_times" as "start_st" on "t"."trip_id" = "start_st"."trip_id"
inner join "stops" as "start_s" on "start_st"."stop_id" = "start_s"."stop_id"
inner join "stop_times" as "end_st" on "t"."trip_id" = "end_st"."trip_id"
inner join "stops" as "end_s" on "end_st"."stop_id" = "end_s"."stop_id"
inner join "stop_times" as "last_st" on "t"."trip_id" = "last_st"."trip_id"
inner join "stops" as "last_s" on "last_st"."stop_id" = "last_s"."stop_id"
where "start_s"."stop_id" = '245' -- my data's stop id
and "end_s"."stop_id" = '762' -- my data's stop id
and "last_st"."stop_sequence" = (select max("stop_sequence") from "stop_times" where "t"."trip_id" = "trip_id")
and start_st.departure_time < end_st.arrival_time
order by arrival_time asc

Mysql select in 1 table, update 2 table

There are three tables:
shop_product_skus - a table for the item 1 product ( 1 to many )
shop_product_skus(id,product_id,sku,sort,name,image_id,price,primary_price,purchase_price,compare_price,count,available,dimension_id,file_name,file_size,file_description,virtual)
shop_product_stocks - a table of how many products in different warehouses
shop_product_stocks(sku_id, stock_id, product_id, count)
shop_product_ostatki - this is a temporary table with the amount of product , price and sku from one warehouse , for example stock_id = 1 ( 1 is updated every 30 minutes)
shop_product_ostatki (id, sku, count, price)
Foreign Key Relations
shop_product_skus.product_id = shop_product_stocks.product_id
shop_product_skus.sku = shop_product_ostatki.sku
shop_product_skus.id = shop_product_stocks.sku_id
Now I need to update data from shop_product_ostatki
In table shop_product_skus
update shop_product_skus.price = shop_product_ostatki.price * 1.07,
shop_product_skus.purchase_price = shop_product_ostatki.price * 0.7
where shop_product_skus.sku = shop_product_ostatki.sku
In table shop_product_stocks
update if there is no prompt to add
shop_product_stocks.count = shop_product_ostatki.count,
shop_product_stocks.price = shop_product_ostatki.price * 1.07
where shop_product_skus.sku = shop_product_ostatki.sku
and shop_product_skus.id = shop_product_stocks.sku_id
Probably explained a little confusing , I do it all in one query.
For 4 days I struggle with this issue, search by stackoverflow enjoyed similar questions not found :(
ps sorry for my english
UPDATE
http://sqlfiddle.com/#!2/90f67
UPDATE
I'm try this, it's not worked
INSERT INTO shop_product_stocks (sku_id ,stock_id ,product_id ,'count')
(SELECT id.b ,product_id.b ,sku.b ,sort.b ,name.b ,image_id.b, price.b ,primary_price.b ,purchase_price.b ,available.b FROM shop_product_skus b
LEFT JOIN shop_product_ostatki c ON c.sku = b.sku
LEFT JOIN shop_product_skus a ON a.sku = c.sku
WHERE shop_product_stocks.stock_id = 1
)
ON DUPLICATE KEY UPDATE
'count' = 'count'.c
UPDATE
error in select
SELECT * FROM shop_product_skus AS b
LEFT JOIN shop_product_ostatki_sander AS c ON c.sku = b.sku
LEFT JOIN shop_product_stocks AS a ON a.sku_id = b.id
WHERE a.stock_id = 1
but all expr not worked

SQL Left Join but don't want all records in the left table

I have 2 tables - Projects and Status Updates. The Project table has fields for id, priority, and status (among others) and my Status update table has fields for ProjectID, and date among others.
I am trying to build a query that will pull all of the High priority projects that are not completed or cancelled and tell me which of those do not have a status update associated with them in the last 14 days.
I have the following, but it is giving me all projects from the left table and not filtering on High priority projects who's status is not Completed or Cancelled.
ANY HELP WOULD BE GREATLY APPRECIATED.
Select proj.id, proj.Priority, proj.status, proj.ProjectName, status_tmp.statusdate, status_tmp.statusdetail
FROM proj
LEFT JOIN (SELECT s1.*
FROM projectstatus AS s1
LEFT JOIN projectstatus AS s2
ON s1.statusproj = s2.statusproj AND s1.statusdate < s2.statusdate
WHERE s2.statusproj IS NULL ) as status_tmp
ON (proj.id=status_tmp.statusproj)
where proj.Priority='High' AND proj.status!='Cancelled' and
proj.status!='Completed' AND
status_tmp.statusdate < DATE_SUB(CURDATE(),INTERVAL 14 DAY) OR
status_tmp.statusdate IS null
Try putting a parenthesis in the last part of your where clause as so:
Select proj.id, proj.Priority, proj.status, proj.ProjectName, status_tmp.statusdate, status_tmp.statusdetail
FROM proj
LEFT JOIN (SELECT s1.*
FROM projectstatus AS s1
LEFT JOIN projectstatus AS s2
ON s1.statusproj = s2.statusproj AND s1.statusdate < s2.statusdate
WHERE s2.statusproj IS NULL ) as status_tmp
ON (proj.id=status_tmp.statusproj)
where proj.Priority='High' AND proj.status!='Cancelled' and
proj.status!='Completed' AND
(status_tmp.statusdate < DATE_SUB(CURDATE(),INTERVAL 14 DAY) OR
status_tmp.statusdate IS null )
If your status table has only the ProjectID as key:
SELECT P.*
FROM
proj P
LEFT JOIN projectstatus S ON P.id = S.ProjectID
WHERE
P.Priority = 'High'
AND P.status NOT IN ('Cancelled', 'Completed')
AND
(
S.statusdate < DATE_SUB(CURDATE(), INTERVAL 14 DAY)
OR
S.statusdate IS NULL
)
Otherwise you'll need filtering on the status table as well to select the currentmost status (this may not be true).