show client with minimum number in a sql query - mysql

I have two tables:
client : (backoffice_users_id, idfile, validation_file)
transmission : (backoffice_users_id, idfile, nbr_files)
I want to show the client who has the minimum number of files and with validation_file=1
I did something like this, it gives me the minimum number but with validation_file=0 not validation_file=1, can anyone help me please?
SELECT `transmission`.*
FROM `transmission`
INNER JOIN `client`
ON client.backoffice_users_id=transmission.backoffice_users_id
WHERE (transmission.idfile='2')
AND (client.validation_file<>0)
AND (transmission.nbr_files=(
SELECT min(nbr_files)
FROM transmission
WHERE transmission.idfile='2'))
GROUP BY `client`.`backoffice_users_id`
LIMIT 1

I don't know what your transmission.idfile='2' means so only answering the 'minimum number of files and with validation_file=1'-part and with the minimume number of files within one single transmission (not summed over multiple transmissions):
SELECT * FROM `transmission`
INNER JOIN `client` ON
`client`.`backoffice_users_id` = `transmission`.`backoffice_users_id` AND
`client`.`validation_file` = 1
ORDER BY `transmission`.`nbr_files` ASC
LIMIT 1

Related

GROUP BY clause and contains nonaggregated column issue solve without disabling full groupby variable from SQL

I am facing some groupby aggregation issue in my below join query:
SELECT chat_tbl.chatrec_id,
chat_tbl.senderid,
chat_tbl.receiverid,
chat_tbl.msg,
chat_tbl.chat_time,
chat_tbl.chatuser_strid,
chatuser_link_tbl.str_id,
chatuser_link_tbl.modifytime
FROM chat_tbl
INNER JOIN chatuser_link_tbl ON chat_tbl.chatuser_strid = chatuser_link_tbl.str_id
AND (chat_tbl.senderid=393 OR chat_tbl.receiverid=393)
GROUP by chat_tbl.chatuser_strid
ORDER by chatuser_link_tbl.modifytime DESC
I know I can disable the only_full_group_by setting by executing the following:
set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
But that is the wrong method it will waive off the settings and this is again removed after every server restart so i want to correct my query. Please anyone can help me to correctly write this join query from 3 tables.
Thanks in advance.
Update 1: I am using this query to list all the chat done by the current user with other users.
I have 2 tables to do that chatuser_link_tbl has the link of the chat done between 2 users for example 11-18, 12-22 i.e concatenated 2 user id with dash - and chat table has an actual chat data.
I am using group by to group all the chats using chatuser_strid to get only single last record. I am displaying only last chat message with date time.
In short this is the same as whatsapp chat list (the first home screen) or like facebook messenger chat list. Which display user details with their last chat message.
Since your query is designed to work on a single user (sender or receiver equal to 393) you can simply drop the group by and add a limit
SELECT chat_tbl.chatrec_id,
chat_tbl.senderid,
chat_tbl.receiverid,
chat_tbl.msg,
chat_tbl.chat_time,
chat_tbl.chatuser_strid,
chatuser_link_tbl.str_id,
chatuser_link_tbl.modifytime
FROM chat_tbl
INNER JOIN chatuser_link_tbl ON chat_tbl.chatuser_strid = chatuser_link_tbl.str_id
AND (chat_tbl.senderid=393 OR chat_tbl.receiverid=393)
ORDER by chatuser_link_tbl.modifytime DESC
LIMIT 1
I think you want to use window functions for this:
SELECT *
FROM (SELECT c.*, cl.str_id, cl.modifytime,
ROW_NUMBER() OVER (PARTITION BY c.chat_user_strid ORDER BY cul.modifytime DESC)
FROM chat_tbl c JOIN
chatuser_link_tbl cul
ON c.chatuser_strid = cul.str_id AND
393 IN (c.senderid, c.receiverid)
) c
WHERE seqnum = 1;
I have fixed the issue myself. Below query worked for me to get desired result.
ANY_VALUE helped me.
SELECT chat_tbl.chatuser_strid, ANY_VALUE(chat_tbl.chatrec_id),ANY_VALUE(chat_tbl.senderid),ANY_VALUE(chat_tbl.receiverid),ANY_VALUE(chat_tbl.msg),ANY_VALUE(chat_tbl.chat_time), ANY_VALUE(chatuser_link_tbl.str_id)
FROM chat_tbl
INNER JOIN chatuser_link_tbl
ON chat_tbl.chatuser_strid = chatuser_link_tbl.str_id AND (chat_tbl.senderid=".$userid." OR chat_tbl.receiverid=".$userid.")
GROUP by chat_tbl.chatuser_strid
ORDER by ANY_VALUE(chatuser_link_tbl.modifytime) DESC

I need to sort by the most changed GROUP by in a table

I have a MySQL table called EssayStats with three columns, EssayDate, WordCount and EssayId.
Each row is a record of when the bot recorded how many words were in an essay at a particular point in time.
I'm trying to write a query that will group by EssayId and sort by the largest increase in WordCount from a particular EssayDate to an ending EssayDate.
I'm not really sure where to start. I've tried a handful of things but they obviously don't accomplish what I jeed. My most recent query attempt was
SELECT *
FROM EssayStats
WHERE EssayDate >= "2014-01-01" AND EssayDate <= "2014-05-31"
GROUP BY EssayId
ORDER BY (WordCount)
Start by getting the dates at the beginning and end for each essay. Then join back the original tables to get the counts and do some arithmetic:
select es.EssayId, (esmax.WordCount - esmin.WordCount)
from (select es.EssayId, min(es.EssayDate) as mined, max(es.EssayDate) as maxed
from EssayStats es
group by es.EssayId
) es join
EssayStats esmin
on es.EssayId = esmin.EssayId and es.mined = esmin.EssayDate join
EssayStats esmax
on es.EssayId = esmax.EssayId and es.maxed = esmax.EssayDate;

SQL RAND Query selecting all records and not using joined table

Please can someone talk me through a query that I have inherited through a website I am developing.
The query is returning a random group of 5 products based on the category number 56. There is an issue with the query because it is not restricting the selection based on the product on web and product archive conditions.
AND p.product_OnWeb = 1
AND p.product_Archive = 0
The above lines in the query aren't being adhered to. Instead the query is including all products even when they are marked as p.product_Archive=1 (Archived) and p.product_OnWeb = 0 (Not Online)
If someone could point out where I need to make a change I'd be grateful.
The query in full is:-
SELECT c.prdt_cat_rel_Product_ID,
ROUND(RAND() * x.m_id) 'rand_ind'
FROM tbl_prdtcat_rel c,
tbl_products p,
(SELECT MAX(t.prdt_cat_rel_Cat_ID) 'm_id'
FROM tbl_prdtcat_rel t) x
WHERE c.prdt_cat_rel_Cat_ID = 56
AND p.product_OnWeb = 1
AND p.product_Archive = 0
ORDER BY rand_ind
LIMIT 3
Thankyou
First, to make it easier, convert the query to the newer join syntax
SELECT c.prdt_cat_rel_Product_ID, ROUND(RAND() * x.m_id) 'rand_ind'
FROM tbl_prdtcat_rel c,
JOIN tbl_products p ON p.??? = c.???
JOIN (
SELECT MAX(t.prdt_cat_rel_Cat_ID) 'm_id' FROM tbl_prdtcat_rel t
) x ON 1=1
WHERE c.prdt_cat_rel_Cat_ID = 56
AND p.product_OnWeb = 1
AND p.product_Archive = 0
ORDER BY rand_ind
LIMIT 3
You can see that the query doesn't know how to select match records from P based on C, so it grabs them all.. You need to specify how to match tbl_prdtcat records with tbl_product records (replace the ??? in the above with the appropriate fields)
I am guessing each product in p has some sort of field indicating which category it belong to, use this field to match and your query should work...

Using COUNT and NOT IN to find total results

Here's my current query I'm using
SELECT *
FROM accounts
WHERE source = 0
AND account_id NOT IN(SELECT receive FROM actions WHERE follow = '$account')
AND status = 0
ORDER BY RAND() LIMIT
I want to somehow do something like this
SELECT *
FROM accounts
WHERE source = 0
AND account_id NOT IN(SELECT * FROM actions WHERE follow = '$account')
AND COUNT((SELECT * FROM actions WHERE follow = '$account')) AS `total_received_follows`
AND total_received_follows < max_follows
AND status = 0
ORDER BY RAND() LIMIT
I basically need to get COUNT the amount of rows that have a follow value of '$account' from the actions table I then want to check this value has a lower value than the row max_follows from the accounts table
I understand that's probably not the correct syntax, but is their anyway I can do something like that using the query I have?
I'm a little confused, but here goes... In your second query, you're looking for accounts that don't have any corresponding rows in actions? But it also looks like you're trying to find accounts that have less than max_follows rows in actions. Am I right? You realise this is contradictory?
Regardless, this might be a place to start:
SELECT acc.*, COUNT(act.id) act_count FROM accounts acc
LEFT JOIN action act ON act.follow = acc.id
WHERE ...
GROUP BY acc.id
HAVING act_count < acc.max_follows

Counting the number min records within groups

I'm building a report for a database where I need to determine the number of "first scans" grouping by company, job, and date.
The scan table can contain multiple scans for the same item, however I only want to include the original scan in my COUNT, which can only be identified as being the scan with the earliest date that matches a particular item.
My first attempt at this was:
SELECT
_item_detail.job_id,
_item_group.group_id,
_scan.company_id,
DATE(scan_date_time) as scan_date,
COUNT(1)
FROM _scan
INNER JOIN _item_detail ON _item_detail.company_id = _scan.company_id
AND
_item_detail.serial_number = _scan.serial_number
INNER JOIN _item_group ON _item_group.group_id = _item_detail.group_id
WHERE _item_detail.job_id = '0326FCM' AND _scan.company_id = '152345' AND _item_group.group_id = 13
GROUP BY
_item_detail.job_id,
_item_group.group_id,
_scan.company_id, scan_date -- first_scan_count
HAVING min(scan_date_time);
This is giving me incorrect results, though (about 3x too many). I am assuming it's because the MIN record is being recalculated for each date, so if the min was found on day 1, it may also be found on day 3 and counted again.
How can I modify my query to achieve the desired results?
Something similar to this should work... I'm not completely sure of how your tables are laid out or how the data relates them together, but this is the general idea:
SELECT
_item_detail.job_id,
_item_group.group_id,
_scan.company_id,
DATE(scan_date_time) as scan_date,
COUNT(1)
FROM
_scan s1
INNER JOIN _item_detail
ON _item_detail.company_id = s1.company_id
AND _item_detail.serial_number = s1.serial_number
AND _item_detail.job_id = '0326FCM'
INNER JOIN _item_group
ON _item_group.group_id = _item_detail.group_id
AND _item_group.group_id = 13
WHERE
s1.company_id = '152345'
AND s1.scan_date_time = (
SELECT MIN(s2.scan_date_time)
FROM _scan s2
WHERE
s2.company_id = s1.company_id
AND s2.serial_number = s1.serial_number
)
GROUP BY
_item_detail.job_id,
_item_group.group_id,
s1.company_id
I don't quite follow your query, but based on the description of the problem, I'd say create a subquery that gives the min scan date for for each item, group by items, the perform your outer select on that.