INSERT INTO SELECT WHERE col = col - mysql

Please can someone help me, I have a table of users and another table with users and date time (this is a log file and multiple dates exist per user). I need to take the most recent date from the log table and insert it into the first table next to the same user.
This is what I have but its not working:
INSERT INTO tb1 n (DT)
SELECT w.DT
FROM tb2 w
WHERE w.User = n.User
ORDER BY w.DT DESC
limit 1

you don't need to use INSERT statement here since there are already records present on your table. But instead UPDATE it with JOIN
UPDATE tb1 a
INNER JOIN
(
SELECT user, MAX(DT) maxDT
FROM tb2
GROUP by user
) b ON a.user = b.user
SET a.DT = b.maxDT

Related

SQL Select two records if they have certain time difference of column A and have same column B value

I have 14000 records in my sql table. They have columns ID, test_subject_id and date_created. I want to fetch all the records that have been created within a time difference of 3 minutes(difference in date_created values) and both records should have the same test_subject_id.
You should use a self join, I assume inner join is what will work for you:
SELECT a.ID, a.date_created, b.ID, b.date_created
FROM accounts a
INNER JOIN accounts b
ON a.test_subject_id = b.test_subject_id
AND TIMESTAMPDIFF(MINUTE,a.date_created,b.date_created) = 3
Note: TIMESTAMPDIFF is used assuming date_created has type datetime, details here.
You can use EXISTS:
SELECT t1.*
FROM tablename t1
WHERE EXISTS (
SELECT 1
FROM tablename t2
WHERE t2.test_subject_id = t1.test_subject_id
AND ABS(TIMESTAMPDIFF(SECOND, t1.date_created, t2.date_created)) <= 180
)
ORDER BY t1.test_subject_id, t1.date_created;

Unable to Resovle MySQL Statement

I have one Master Table with Client_ID and other details of Client. The Second Table is a daily records tabel linked to master Table on Client_ID and has additional column for recording current date. Hence, the Client_ID in the second table has repetitie records based on each date.
I am trying to Select such Records with Client_ID From Master Table for Which Records of Current Date do not exist.
My attempted SQL Statement is as follows:-
SELECT `Client_ID`, `Client_RFID_Number`
FROM ciom_master AS a
WHERE (`Client_Active` ='Y' OR `Client_Active` ='y')
AND CURDATE() NOT EXISTS (
SELECT (`Client_Check_Out`)
FROM `cio_master` AS b
WHERE a.Client_ID = b.Client_ID )
AND CURDATE() NOT EXISTS (
SELECT (`Client_Check_In`)
FROM `cio_master` AS c
WHERE a.Client_ID = c.Client_ID )
I am unable to resolve this statement error. Please help.
You need to move the CURDATE() inside the NOT EXISTS queries:
SELECT `Client_ID`, `Client_RFID_Number`
FROM ciom_master AS a
WHERE (`Client_Active` ='Y' OR `Client_Active` ='y')
AND NOT EXISTS (
SELECT (`Client_Check_Out`)
FROM `cio_master` AS b
WHERE a.Client_ID = b.Client_ID
and Client_Check_Out = CURDATE() )
AND NOT EXISTS (
SELECT (`Client_Check_In`)
FROM `cio_master` AS c
WHERE a.Client_ID = c.Client_ID
and Client_Check_In = CURDATE())

mysql update table column with multiple values from same table

I have a mysql table with columns: customer, dateOrder.
One customer can have orders in multiple dates. I want to add a new column with the farthest date order for each customer. So far i tried this:
UPDATE mytable
SET MINDATE = (SELECT min(DATEORDER)
FROM (SELECT *
FROM mytable
GROUP
BY CUSTOMER
) tblTmp
)
, where tblTmp is a temporary table;The problem is that it brings the same date for all my customers (the farthest date in the table). Any ideas?
Use a JOIN to match the original table with the subquery:
UPDATE mytable AS t1
JOIN (SELECT customer, MIN(dateorder) AS mindate
FROM mytable
GROUP BY customer) AS t2 ON t1.customer = t2.customer
SET t1.mindate = t2.mindate

How do I write this kind of query (returning the latest avaiable data for each row)

I have a table defined like this:
CREATE TABLE mytable (id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
user_id INT REFERENCES user(id) ON UPDATE CASCASE ON DELETE RESTRICT,
amount REAL NOT NULL CHECK (amount > 0),
record_date DATE NOT NULL
);
CREATE UNIQUE INDEX idxu_mybl_key ON mytable (user_id, amount, record_date);
I want to write a query that will have two columns:
user_id
amount
There should be only ONE entry in the returned result set for a given user. Furthermore, the amount figure returned should be the last recoreded amount for the user (i.e. MAX(record_date).
The complication arises because weights are recorded on different dates for different users, so there is no single LAST record_date for all users.
How may I write (preferably an ANSI SQL) query to return the columns mentioned previously, but ensuring that its only the amount for the last recorded amount for the user that is returned?
As an aside, it is probably a good idea to return the 'record_date' column as well in the query, so that it is eas(ier) to verify that the query is working as required.
I am using MySQL as my backend db, but ideally the query should be db agnostic (i.e. ANSI SQL) if possible.
First you need the last record_date for each user:
select user_id, max(record_date) as last_record_date
from mytable
group by user_id
Now, you can join previous query with mytable itself to get amount for this record_date:
select
t1.user_id, last_record_date, amount
from
mytable t1
inner join
( select user_id, max(record_date) as last_record_date
from mytable
group by user_id
) t2
on t1.user_id = t2.user_id
and t1.record_date = t2.last_record_date
A problem appears becuase a user can have several rows for same last_record_date (with different amounts). Then you should get one of them, sample (getting the max of the different amounts):
select
t1.user_id, t1.record_date as last_record_date, max(t1.amount)
from
mytable t1
inner join
( select user_id, max(record_date) as last_record_date
from mytable
group by user_id
) t2
on t1.user_id = t2.user_id
and t1.record_date = t2.last_record_date
group by t1.user_id, t1.record_date
I do not now about MySQL but in general SQL you need a sub-query for that. You must join the query that calculates the greatest record_date with the original one that calculates the corresponding amount. Roughly like this:
SELECT B.*
FROM
(select user_id, max(record_date) max_date from mytable group by user_id) A
join
mytable B
on A.user_id = B.user_id and A.max_date = B.record_date
SELECT datatable.* FROM
mytable AS datatable
INNER JOIN (
SELECT user_id,max(record_date) AS max_record_date FROM mytable GROUP BS user_id
) AS selectortable ON
selectortable.user_id=datatable.user_id
AND
selectortable.max_record_date=datatable.record_date
in some SQLs you might need
SELECT MAX(user_id), ...
in the selectortable view instead of simply SELECT user_id,...
The definition of maximum: there is no larger(or: "more recent") value than this one. This naturally leads to a NOT EXISTS query, which should be available in any DBMS.
SELECT user_id, amount
FROM mytable mt
WHERE mt.user_id = $user
AND NOT EXISTS ( SELECT *
FROM mytable nx
WHERE nx.user_id = mt.user_id
AND nx.record_date > mt.record_date
)
;
BTW: your table definition allows more than one record to exist for a given {id,date}, but with different amounts. This query will return them all.

Merge and then Delete duplicate entries

I have mySQL database with some duplicate entries. They have the same field - phone. But they also had fields which differs. At example I have two entries with same phone, but first entry has rating filed = default_value and second entry has rating field = 5.
So I must merge this entries and only then delete duplicates...
More common example:
entry1.phone==123
entry1.phone==etry2.phone
entry1.rating!=entry2.phone
entry1.rating==default_value(0)
entry2.rating==5
merge
entry1.phone==123
entry1.rating==5
entry2 is deleted
I don't think you can do this in SQL efficiently. One slow way to do it is something like:
CREATE TEMPORARY TABLE tmp_table (...);
INSERT INTO tmp_table SELECT phone, max(rating) FROM table GROUP BY phone;
TRUNCATE table;
INSERT INTO table SELECT * FROM tmp_table;
A better way would be a stored procedure or an external script. Select all rows from the table ordered by phone and do the grouping/merging/deleting manually (iterate over the results, compare to the phone value from the previous row, if it's different you have a new group, etc.). Writing stored procedures in MySQL is painful though, so I'm not going to write the code for you. :)
It sounds like you don't really need to merge any records if you are just trying to update the first record with the non-default rating. I think you can just delete any records with the default rating.
Select a.*
from tbl a
inner join tbl b
on a.Phone = b.Phone
and a.Rating < b.Rating
Delete a
from tbl a
inner join tbl b
on a.Phone = b.Phone
and a.Rating < b.Rating
If you truly have to update the first record and delete the second record, you can do something similar if you have an autoincrement ID. The next example is what I would do to update the first record if an ID exists. This is only reliable if you only have phone numbers duplicated one time.
Update a
Set a.Rating = b.Rating
from tbl a
inner join tbl b
on a.Phone = b.Phone
and a.Rating < b.Rating
and a.ID < b.ID
Delete a
from tbl a
inner join tbl b
on a.Phone = b.Phone
and a.Rating = b.Rating
and b.ID > a.ID
Hope this helps.
-Ranthalion