Mysql return value with nested Select - mysql

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.

Related

Get products without sales for last 7day

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;

MySQL query returning only one row because of SUM function in it

I am trying to create an advertisement query where I want to fetch data of all the impressions per advertisement. One user can have multiple advertisements and impressions will be counted in a table on per day basis. So for each day I will have one different row. Here is how my query currently looks like.
SELECT
eac.id,
eac.gender,
eac.start_date,
eac.end_date,
eac.ad_image_path,
eac.ad_link,
eac.requestfrom,
eac.traffic,
eac.registertype,
eacr.region_id,
eac.active,
eac.impression,
eac.center_image_path,
eac.bottom_image_path,
eac.approved_by,
er.name as country_name,
eac.budget,
sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp,
eaa.impression_count,
eac.customer_id,
eaa.created_at
FROM
`enrich_advert_customer` eac
JOIN `enrich_advert_customer_regions` eacr ON eac.id = eacr.advert_customer_id
JOIN `enrich_regions` er ON er.id = eacr.region_id
LEFT JOIN `enrich_advert_abstract` eaa on eac.id = eaa.advert_customer_id
WHERE
eac.requestfrom ='web' AND
eac.registertype = 'paid' AND
eac.active = 1 AND
eac.approved_by = 1 AND
eac.gender ='male' AND
er.name = 'india' AND
eac.start_date <= '2018-11-5' AND
eac.end_date >= '2018-11-10'
But the problem here is if I am using
sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp
this then its returning only one row at a time.
If you can suggest where I am making a mistake that will be helpful.
Thank you!
You need to add group by clause and others column in there as you applyied aggregation
SELECT eac.id,eac.gender,eac.start_date,eac.end_date,eac.ad_image_path,eac.ad_link,eac.requestfrom,eac.traffic,eac.registertype,eacr.region_id,eac.active,eac.impression,eac.center_image_path,eac.bottom_image_path,eac.approved_by,er.name as country_name,eac.budget,sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp ,eaa.impression_count,eac.customer_id,eaa.created_at
FROM
`enrich_advert_customer` eac
JOIN
`enrich_advert_customer_regions` eacr
ON eac.id = eacr.advert_customer_id
JOIN
`enrich_regions` er
ON er.id = eacr.region_id
LEFT JOIN
`enrich_advert_abstract` eaa
on eac.id = eaa.advert_customer_id
WHERE eac.requestfrom ='web' AND
eac.registertype = 'paid' AND
eac.active = 1 AND
eac.approved_by = 1 AND
eac.gender ='male' AND
er.name = 'india' AND
eac.start_date <= '2018-11-5' AND
eac.end_date >= '2018-11-10'
group by eac.id,eac.gender,eac.start_date,eac.end_date,eac.ad_image_path,eac.ad_link,eac.requestfrom,eac.traffic,eac.registertype,eacr.region_id,eac.active,eac.impression,eac.center_image_path,eac.bottom_image_path,eac.approved_by,er.name,eac.budget, eaa.impression_count,eac.customer_id,eaa.created_at

Counting entry in a column MySQL and display counts

I would want to count entries in a column and display the count beside it.
However, I'm clueless on how can I do it.
Desired output:
arrangement_number tray_no rl_type flag(count of occurrence)
------------------ ------- ---- ----
2774818 381001 R 3
2774818 381001 R 3
2774818 381001 L 3
2778470 405128 R 1
2779702 265265 R 2
2779702 265265 R 2
I'm currently trying queries using #variables but I still cant get it right.
each row are unique and I need them not to be grouped.
Update: Expanded Table added source code
Note: I'm currently joining 5 tables now
Actual Query:
SELECT
log.arrangement_number,
header.tray_number,
detail.rl_type,
-- some more fields here
FROM
log
INNER JOIN
header ON log.arrangement_number = header.rxarrangement_number
AND log.production_place_code = header.production_place_code
INNER JOIN
detail ON log.arrangement_number = detail.rxarrangement_number
AND log.production_place_code = detail.production_place_code
INNER JOIN
deliveryperiod ON log.arrangement_number = deliveryperiod.arrangement_number
AND log.production_place_code = deliveryperiod.production_place_code
AND detail.rl_type = deliveryperiod.rl_type
INNER JOIN
calc ON calc.arrangement_number = log.arrangement_number
AND calc.production_place_code = log.production_place_code
AND deliveryperiod.rl_type = calc.rl_type
AND detail.rl_type = calc.rl_type
WHERE
header.status_code IN ('20' , '21')
AND log.process_code = '12'
AND deliveryperiod.process_code_current = '12'
AND deliveryperiod.sub_process_code_current IN ('100' , '105')
AND lot_number = '120131'
ORDER BY log.lot_number , log.sequence_number , deliveryperiod.rl_type DESC
SELECT t1.tray_no,
t2.flag
FROM yourTable
INNER JOIN
(
SELECT tray_no, COUNT(*) AS flag
FROM yourTable
GROUP BY tray_no
) t2
ON t1.tray_no = t2.tray_no
try this...
SELECT tray_no, COUNT(*) 'flag'
FROM table1
GROUP BY tray_no

How do I select one row but no more from foreign key ? ---- Group BY ---

I have this statement that works fine without the below statement.
I think I may be using the incorrect statement. What I'm trying to do is only select the first productsapplied.applicationid. If another row has the same productsapplied.applicationid as one already selected it won't select it. There can be more than one of the same application id but I need it to only add 1.
DISTINCT('productsapplied'.applicationid)
'SELECT `productsApplied`.id, DISTINCT(`productsApplied`.applicationid)
FROM `productsapplied`
INNER JOIN `products`
ON `productsApplied`.productid = `products`.id
INNER JOIN `applications`
ON `productsApplied`.applicationid = `applications`.id
WHERE `applications`.clubid = ? AND `applications`.area = ? AND EXTRACT(YEAR FROM `applications`.date) = ? AND `products`.producttype = ?
If anyone has any ideas, would appreciate it!
If not I was thinking of just doing a COUNT DISTINCT
Lets say that here are the products applied
id: 3 clubid:6 applicationid: 5 ...
id: 4 clubid:6 applicationid: 5 ...
id: 5 clubid:6 applicationid: 5 ...
id: 4 clubid:6 applicationid: 6 ...
Presuming the rest of the statement holds e.g. year = ? etc..
Then the number of rows returned would be 2. AS there are 3 rows with the same application id. No matter how many rows there are with the same application id, one should be counted.
DISTINCT is applied is to whole row not to a single column for your concern there will be different productsApplied.ids per applicationid so you can grab all by using group_concat
SELECT
GROUP_CONCAT(pa.id),
`pa`.applicationid
FROM
`productsapplied` pa
INNER JOIN `products` p
ON `pa`.productid = `p`.id
INNER JOIN `applications` a
ON `pa`.applicationid = `a`.id
WHERE `a`.clubid = ?
AND `a`.area = ?
AND EXTRACT(YEAR FROM `a`.date) = ?
AND `p`.producttype = ?
GROUP BY `pa`.applicationid
If you are not concerned with productsApplied.ids then you can simple use the group by part but note group by without aggregate function will result in indeterminate order
Edit
This will give you one max id per applicationid
SELECT
SUBSTRING_INDEX(GROUP_CONCAT(pa.id ORDER BY pa.id DESC), 1),
`pa`.applicationid
FROM
`productsapplied` pa
INNER JOIN `products` p
ON `pa`.productid = `p`.id
INNER JOIN `applications` a
ON `pa`.applicationid = `a`.id
WHERE `a`.clubid = ?
AND `a`.area = ?
AND EXTRACT(YEAR FROM `a`.date) = ?
AND `p`.producttype = ?
GROUP BY `pa`.applicationid
or
SELECT
MAX(pa.id),
`pa`.applicationid
FROM
`productsapplied` pa
INNER JOIN `products` p
ON `pa`.productid = `p`.id
INNER JOIN `applications` a
ON `pa`.applicationid = `a`.id
WHERE `a`.clubid = ?
AND `a`.area = ?
AND EXTRACT(YEAR FROM `a`.date) = ?
AND `p`.producttype = ?
GROUP BY `pa`.applicationid
Select min(pa.id), pa.applicationid
From productsapplied pa
Join ...
...
Group by pa.applicationid

MySQL SELECT DISTINCT ORDER BY problem

To begin with I have 4 tables I am dealing with.
I have a classes table that is a 1->N relationship with a sections table which also has a 1->N relationship with a lessons table.
So to put it in perpective:
Classes
Sections
Lessons
The last table is an activityLog, when the student accesses a lesson this is recorded using the following:
ActivityLog Row -> actorID (user ID), classID, sectionID, lessonID
I want to pull out the last 5 unique lessons the student has visited. I tried using both DISTINCT and GROUP BY without success.
The same records are being returned each time, not the latest classes that they have visited.
Using GROUP BY
SELECT activityLog.actorID, activityLog.activityDate,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
GROUP BY activityLog.lessonID
ORDER BY activityLog.activityDate DESC
LIMIT 5
Using DISTINCT
SELECT DISTINCT activityLog.actorID,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
ORDER BY activityLog.activityDate DESC
LIMIT 5
I cannot figure out why the latest records are not being displayed.
Based on your change, how does this suit you?
SELECT activityLog.actorID, activityLog.activityDate,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
AND activityLog.activityDate = (SELECT MAX(activityDate) FROM activityLog AS lookup WHERE lessonID = activityLog.lessonID)
ORDER BY activityLog.activityDate DESC
LIMIT 5
Based on your description, I'm not sure why you're using LEFT JOIN, but I've left it in just in case.
Try group by like below
GROUP BY activityLog.classID,activityLog.sectionID,activityLog.lessonID
I think it will work, or just sent me create scripts for these I will create that query
Well, there's got to be a datetime in the ActivityLog I hope... so Try this:
Select s.Name, c.ClassName
From Students s
left Join On Classes c
On c.ClassId In
(Select Distinct ClassId From Classes
Where (Select Count(Distinct ClassId) From Classes ic
Join ActivityLog l On l.UserId = s.UserId
And l.ClassId = c.ClassId
Where classId = c.ClassId
And activityDateTime > l.activityDateTime)
< 5)