comparing in the same table based on latest creation date - mysql

id|code|transaction_date |amount|status|record_status|creation_date
1 |0001|2021-12-10 00:00:00| 10.00|Succ |D |2021-12-10 00:00:00
2 |0001|2021-12-10 00:00:00| 10.00|Fail |D |2021-12-11 00:00:00
3 |0001|2021-12-10 00:00:00| 10.00| |A |2021-12-12 00:00:00
I want to select recod_status = A, code = 001 and transaction date is 2021-12-10'
SELECT * FROM TestTable
WHERE DATE(alloc.trans_date) IN ('2021-12-10') // Need filter by few dates
AND record_status = 'A'
AND code = '001';
but I only want the record to return if the same code = 001 and transaction date is 2021-12-10' but record_status = 'D', status = 'Fail' and the creation_date is latest.
Example above will return 3rd record because 2nd record which creation_date is the latest and status = 'Fail' and record_status = 'D'.
I just want to compare the latest creation_date.'
I can select the latest transaction where the record_status = 'D'
SELECT * FROM TestTable
WHERE creation_date = (
SELECT MAX(creation_date)
FROM TestTable
WHERE DATE(trans_date) IN ('2021-12-10')
AND record_status = 'D'
)
AND record_status = 'D'
AND code = '001';

Looks like:
SELECT t1.*
-- or SELECT t2.* - depends on the task which is unclear for me yet
FROM ( SELECT *
FROM table
WHERE DATE(trans_date) = '2021-12-10'
ORDER BY creation_date DESC LIMIT 1 ) t1
JOIN table t2 ON DATE(t1.trans_date) = DATE(t2.trans_date)
AND t1.creation_date > t2.creation_date
WHERE t1.record_status = 'A'
AND t2.record_status = 'D'
AND NOT EXISTS ( SELECT NULL
FROM table t3
WHERE DATE(t1.trans_date) = DATE(t3.trans_date)
AND t1.creation_date > t3.creation_date
AND t3.creation_date > t2.creation_date )
Subquery t1 selects the most last row, and further it is checked for status A.
Table copy t2 selects the row which is adjacent to the row selected in subquery (NOT EXISTS checks that there is no any row between), and further it is checked for status D.

Related

get the total count but exclude certain condition

Hello I had this table:
id | user_id | status
1 | 34 | x
2 | 35 | x
3 | 42 | x
4 | 42 | y
My goal is to count the data with X status except if the user has a another data with Y status, it will exclude in the count. So instead of 3, it will only count 2 since the 3rd row has another data which is the 4th row with y status.
SELECT * FROM logs
AND user_id NOT IN (SELECT user_id FROM logs WHERE status = 'y')
GROUP BY user_id;
We can try the following aggregation approach:
SELECT COUNT(*) AS cnt
FROM
(
SELECT user_id
FROM logs
GROUP BY user_id
HAVING MIN(status) = MAX(status) AND
MIN(status) = 'x'
) t;
The above logic only counts a user having one or more records only having x status.
You can do it this way, I only modify a bit on your sql
SELECT COUNT(*) FROM (
SELECT u_id FROM tbl WHERE u_id NOT IN
(SELECT u_id FROM tbl WHERE status = 'y')
GROUP BY u_id
) as t
You can use inner join:
SELECT
count(t1.id) AS `cnt`
FROM
`test` AS t1,
`test` AS t2
WHERE
t2.`status`='y'
&& t1.`user_id` != t2.`user_id`;

Mysql - Update only 1 row from same records

I need to update row which having same value in debit column & only row which having create_date ASC basically 2019-11-15
I am having transaction table with following data
table name - tbl_transactions
id client_id user_id debit add_date
1 9991101 1 7.69 2019-11-15
2 9991101 1 7.69 2019-11-30
3 9991101 2 28.9 2019-11-15
4 9991101 2 11.49 2019-11-30
Now i just want to UPDATE record which have same value in column "debit" & date "2019-11-15"
which means only id-1 will be get updated.
id client_id user_id debit add_date
1 999110100 1 7.69 2019-11-15
We can add additional 00 to client_id field, i have tried with below sql but seems its not working
UPDATE tbl_transactions
SET client_id=999110100
WHERE id IN (
SELECT *
FROM tbl_transactions
WHERE client_id=9991101
AND DATE(create_date)='2019-11-15'
GROUP BY user_id, debit HAVING COUNT(*) = 2 )
Thanks in advance.
From what I understood from your question, you can try a query like
UPDATE
`tbl_transactions`
SET
`COLUMN_NAME` = DESIRED_VALUE
WHERE
`debit` = 7.69
AND
`add_date` = '2019-11-15'
You just need to replace COLUMN_NAME in the above query with your desired column name and it's respective value ahead of it. Do let me know if that's what you're trying to achieve or something else.
Mysql cannot specify target table for update in FROM clause.
You need to use subquery select them in a temporary table and update it,
And you can use CONCAT to concat your client_id with 00,
According to your post, you need the same debit and order by created_date ASC,
however, mysql cannot just order a field in group, so you can do it like this:
UPDATE
`tbl_transactions`
SET
`client_id` = CONCAT(client_id, '00')
WHERE id IN (
SELECT id FROM (
SELECT t2.id, t2.user_id t2.created_date FROM
(
SELECT id, user_id, MIN(created_date) AS created_date
FROM tbl_transactions
WHERE client_id=9991101
GROUP BY user_id, debit
HAVING COUNT(*) >= 2
) AS t1
INNER JOIN tbl_transactions AS t2
ON t1.user_id = t2.user_id AND t1.debit = t2.debit AND t2.client_id = 9991101 AND t1.created_date = t2.created_date
GROUP BY t2.user_id
) AS temp_table
)

MySQL - Select results with specified ID or with null

I have one table:
| ID | ADV_ID | USER_ID |
| 1 | 22 | NULL |
| 2 | 22 | 3 |
| 5 | 44 | NULL |
and now, I want to select row where adv_id = 22 and user_id = 3. If that row doesn't exist, I want to get row where adv_id = 22 and user_id is null.
I tried in that way:
SELECT * FROM `table` WHERE adv_id = 22 AND (user_id = 3 OR user_id is null)
but this query return two rows - with user_id = NULL and with user_id = 3. I want to get one row - with user_id = 3 or (if not exist), with user_id = NULL.
How I can do it in one query?
Thanks.
Use conditional aggregation:
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT
ADV_ID,
CASE WHEN COUNT(CASE WHEN USER_ID = 3 THEN 1 END) > 0 THEN 3 END USER_ID
FROM yourTable
) t2
ON t1.ADV_ID = t2.ADV_ID AND
((t1.USER_ID IS NULL AND t2.USER_ID IS NULL) OR (t1.USER_ID = t2.USER_ID))
WHERE
t1.ADV_ID = 22;
Demo
For an explanation, the subquery I have aliased as t2 aggregates over the ADV_ID, and outputs the value 3 if that value occurs in one or more records, otherwise it outputs NULL. Then, we join this subquery back to your original table on the condition that both USER_ID values are NULL, or, if not, that the two USER_ID values match.
You may modify the demo to see that it generates the output you want for other inputs.
SELECT *
FROM test
WHERE ADV_ID IS NOT NULL AND USER_ID IS NOT NULL
UNION ALL
SELECT *
FROM test
WHERE USER_ID IS NULL AND NOT EXISTS (
SELECT 1
FROM test
WHERE ADV_ID IS NOT NULL AND USER_ID IS NOT NULL
)
Select all rows with the first condition: ADV_ID IS NOT NULL AND USER_ID IS NOT NULL
and then UNION ALL with the same table if the first condition is NOT EXISTS.
So we only get results if the first condition is not returned any rows.
The MySQL UNION ALL operator is used to combine the result sets of 2 or more SELECT statements.
try like that:
SELECT * FROM `table` t1 WHERE (t1.adv_id = 44)
AND ((t1.user_id = 3) OR
(NOT EXISTS (select * from `table` t2 where t2.adv_id=t1.adv_id and t2.user_id = 3) AND t1.user_id is null ))
DEMO

HAVING row exist

Following database sample
id | date | customer | ...
-----------------------------------------
1 2016-07-05 1
2 2016-07-05 2
3 2016-07-06 1
4 2016-07-07 1
5 2016-07-07 2
I want to select all customers which have an entry at 2016-07-07, but not at 2016-07-06.
At first, I thought I'd do this using WHERE:
SELECT * FROM table
WHERE EXISTS ( SELECT * FROM table WHERE date = '2016-07-07' )
AND NOT EXISTS ( SELECT * FROM table WHERE date = '2016-07-06' )
GROUP BY customer
but since WHERE is executed before GROUP BY, the result can only by empty - there IS a record in table at 2016-07-06.
So, using HAVING, how would I do this? I am having difficulties checking for row existance in a HAVING clause. Something like:
SELECT * FROM table
GROUP BY customer
HAVING exists date '2016-07-07'
AND not exists date '2016-07-06'
Group by the customer and take only those groups having at least one date entry for 2016-07-07 and none for 2016-07-06
SELECT customer
FROM your_table
GROUP BY customer
HAVING sum(date = '2016-07-07') > 0
AND sum(date = '2016-07-06') = 0
SELECT customer FROM table t
WHERE EXISTS ( SELECT * FROM table t1
WHERE date = '2016-07-07' AND t.customer = t1.customer)
AND NOT EXISTS ( SELECT * FROM table t2
WHERE date = '2016-07-06' AND t.customer = t2.customer)
GROUP BY customer

MySQL merge two tables with different data

The following are my mysql tables
Table 1:
ID | commonID | Date | text | active
1 11 01.02 abc 1
2 11 02.02 123 1
3 11 03.02 xyz 0
Table 2:
ID | commonID | Date | value | active
1 11 01.02 abc 1
2 11 04.02 123 1
3 11 03.02 xyz 1
The Final result should display this:
| date | text | value
01.02 abc abc
02.02 123 (null)
03.02 (null) xyz
04.02 (null) 123
The Idea here is, to merge the two tables. All entries with a defined commonID like 11 in the example will be selected from both tables. then the tables will be united.
Conditions:
If there are matching dates in TABLE1 and TABLE2 they will be merged
If there is a solo date in TABLE1 or TABLE2, the value/text for the table with no date will become NULL
If there is a record in TABLE1 or TABLE2 that has active = FALSE, it will not be processed.
There can be matching and not matching dates in BOTH tables.
I want to use this for display chronologic events, if there is an event in both tables, there should be only one line for this.
What could be the Solution here?
Try this:
SELECT T1.date,
CASE WHEN T1.active = 1 THEN T1.text END as text,
CASE WHEN T2.active =1 THEN T2.value END as value
FROM Table1 T1 LEFT JOIN
Table2 T2 ON T1.date=T2.date
UNION
SELECT T2.date,
CASE WHEN T1.active = 1 THEN T1.text END as test,
CASE WHEN T2.active = 1 THEN T2.value END as value
FROM Table1 T1 RIGHT JOIN
Table2 T2 ON T1.date=T2.date
Result:
DATE TEXT VALUE
01.02 abc abc
02.02 123 (null)
03.02 (null) xyz
04.02 (null) 123
Sample SQL Fiddle.
Try this:
SELECT t1.date,t1.text,t2.value FROM table1 t1
LEFT JOIN table2 t2 ON t1.commonId = t2.commonId and t1.date = t2.date and t2.active = 1
where t1.active = 1
UNION
SELECT t2.date,t1.text,t2.value FROM table2 t2
LEFT JOIN table1 t1 ON t1.commonId = t2.commonId and t1.date = t2.date and t1.active = 1
where t2.active = 1
Sample http://sqlfiddle.com/#!2/d2c4d/2
Here's one way...
SELECT commonid
, date
, MAX(text) text
, MAX(value) value
FROM
( SELECT id
, commonid
, date
, text
, NULL value
, active
FROM table1
WHERE active <> 0
UNION
SELECT id
, commonid
, date
, NULL
, value
, active
FROM table2
WHERE active <> 0
) x
GROUP
BY commonid,date;
You can move the WHERE active <> 0 bit out of the UNIONs if you like, to just before the GROUP BY.