My query in PHP consist of two parts: creating temporary table and the main query.
How should I write this query in PHP?
//Creating temporary table part:
create temporary table mytable as(SELECT `Name`, `Date`, `Condition`
FROM info
ORDER BY `Date` DESC );
//The main query part:
select mytable.Name, mytable.Date, mytable.Condition FROM mytable
right join info on mytable.Name = info.Name
Group by mytable.Name;
Edited: My query contain 3 columns(Name, Date and Condition). I need the rows with max(Date), since I have some rows with the same Name, I should use Group.
The following query does not help:
SELECT `Name`, max(Date), `Condition`
FROM info
Group by Name
ORDER BY min(Date) DESC
Related
I'm running MariaDB 5.5 which is equivalent to MySQL 5.5.
I have the following test data.
CREATE TABLE `dev_test` (
`id` INT NOT NULL AUTO_INCREMENT ,
`date` DATE NOT NULL ,
`venue` INT NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE = InnoDB;
INSERT INTO `dev_test` (`id`, `date`, `venue`) VALUES (NULL, '2019-08-01', '2'),
(NULL, '2019-09-01', '1'), (NULL, '2019-10-01', '2');
INSERT INTO `dev_test` (`id`, `date`, `venue`) VALUES (NULL, '2019-11-01', '3');
I wish to order the venues and the events so that the venue of the next event is first, then all other events at that venue. Then the next event that's not all ready listed.
So with this data I want:
Event ID 1 - 2019-08-01 Venue 2
Event ID 3 - 2019-10-01 Venue 2
Event ID 2 - 2019-09-01 Venue 1
Event ID 4 - 2019-11-01 Venue 3
I could just grab all the events in any order then order them using PHP.
Or I could select with
SELECT venue FROM `dev_test` GROUP BY venue ORDER BY date;
Then using PHP get the venues one at a time ordered by date
SELECT * FROM `dev_test` WHERE venue = 2 ORDER BY date;
SELECT * FROM `dev_test` WHERE venue = 1 ORDER BY date;
But is there a nice way in pure MySQL (MariaDB) to do this?
Maybe some way of giving all venues a temp date column that is the same as the earliest date at that venue?
Or should I just do it in PHP?
Sorry for the title gore. I tried to make "Order events by date whilst keeping events at the same location together" more generic.
Try this query, I think this helps you
SELECT t2.* FROM
(SELECT venue FROM dev_test GROUP BY venue ORDER BY date) AS t1
LEFT JOIN (SELECT * FROM dev_test ORDER BY date) AS t2 ON t1.venue=t2.venue
Here result
You can use window functions with CTEs to achieve this (note: Requires MySQL 8+:
WITH added_initial_date
AS (SELECT id,
date,
venue,
FIRST_VALUE(date)
OVER(
PARTITION BY venue
ORDER BY date) AS 'initial_date'
FROM dev_test),
ranked
AS (SELECT id,
date,
venue,
initial_date,
RANK()
OVER(
ORDER BY initial_date ASC) AS position
FROM added_initial_date)
SELECT id,
date,
venue
FROM ranked
ORDER BY position ASC, date ASC;
Maybe it is not most effective, but it works.
UPDATE: added ordering by date to get closest record first. Here is db-fiddle: https://www.db-fiddle.com/f/puYqhDF53ocRiRys61XH53/0
You can try below - using order by venue desc, date asc
SELECT * FROM `dev_test`
order by venue desc, date asc
E.g. :
SELECT a.*
FROM dev_test a
LEFT
JOIN (SELECT * FROM dev_test ORDER BY date DESC LIMIT 1) b
ON b.venue = a.venue
ORDER
BY b.id IS NULL, date DESC;
This assumes dates are UNIQUE, as per the sample data
i have 2 tables which are join together with the help of UNION and display the records using single while loop.
problem:
now the problem is i want do display records from table(1) and table(2) separately but condition is using only single while loop.
here is the SQL:`
$sql = "(SELECT * FROM subject_first WHERE date BETWEEN '$user_from' AND '$user_to') UNION (SELECT * FROM subject_second WHERE date BETWEEN '$user_from' AND '$user_to')";
is there any way to do it?.sorry to say but i am new to PHP.
any advise is appreciated.
Just add a field to both sides of the query:
(SELECT *, 'subject_first' as `table` FROM subject_first WHERE date BETWEEN '$user_from' AND '$user_to')
UNION
(SELECT *, 'subject_second' as `table` FROM subject_second WHERE date BETWEEN '$user_from' AND '$user_to')
ORDER BY `table`
I added the order by part so you can insert a <br> or whatever to split the results.
I have 2 tables:
Table1
Table2
When I move a row from table1 to table2, I also want to update the datetime field and 1 more field.
Say both table have identical column like this:
id
shipped_by
datetime
other_column
I have the following sql line, but it is not working of course. But I want to have it something like that.
$query = "INSERT INTO table2
SELECT * FROM table1
WHERE id = '$id' UPDATE table2
SET shipped_by='$shipped_by', datetime='$datetime'";
The variable $shipped_by selects the userid, and $datetime date from now.
Can anyone help me with this sql code to make it work? I cannot figure it out.
Thank you.
To insert data form table1 with some column data modified can be done with insert and select without update.. select * should be used here, each column must be listed except for modified ones..
$query = "INSERT INTO table2
SELECT id, '$shipped_by', '$datetime', other_column FROM table1
WHERE id = '$id'";
mysql update syntax doesn't seem to work when I added the subquery.
Are there restrictions on subqueries on update syntax?
doesn't work:
update books set imagename ='name'
where book_ID='(select book_ID from books order by book_ID desc limit 1)';
works:
update books set imagename ='name'
where book_ID='101';
MySQL does have limits on subqueries using the table being updated. So yours is not allowed:
update books
set imagename ='name'
where book_ID = (select book_ID from books order by book_ID desc limit 1);
Instead, you can do:
update books
set imagename ='name'
order by book_ID desc
limit 1;
Here is the explanation in the documentation:
In general, you cannot modify a table and select from the same table
in a subquery. For example, this limitation applies to statements of
the following forms:
DELETE FROM t WHERE ... (SELECT ... FROM t ...);
UPDATE t ... WHERE col = (SELECT ... FROM t ...);
{INSERT|REPLACE} INTO t (SELECT ... FROM t ...);
Exception: The preceding prohibition does not apply if you are using a subquery for the modified table in the FROM clause. Example:
UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);
Here the result from the subquery in the FROM clause is stored as a temporary table, so the relevant rows in t have already been
selected by the time the update to t takes place.
Try This query.
Update books
Set imagename = name"
Where book_ID In (
Select T1.book_ID
From books As T1
Where T1.book_ID = '101'
)
I have a table with named "user-recent-activity" which has following columns: id, userid, activity and datetime. Now, I want to delete the records if any unique userid has more than 50 items, deleting the oldest records. For example, if the user id(lets say 1234) has more than 50 records in this table, then I have to save latest 50 records of user id(1234) and delete the oldest one.
Before inserting, query for the last 50 records with that ID (ordering from newer to older). If there is a 50th, substitute it (via update) instead of inserting a new row.
Assuming you are using a RDBMS that supports standard SQL the following stored procedure should do it.
create procedure remove-old-activities
(
#userid int
)
as
delete from user-recent-activity where userid=#userid and id not in (select top 50 id from user-recent-activity where userid=#userid order by datetime desc)
If you're DB does not support stored procedures then you should be able to use SQL parameters to pass the userid value...
Hope that helps
You could use rank method to precisely defined the rows number and thus delete the rows you want.
delete from tblName where id=
(select id from (
select #i := CASE WHEN ( #userid <> userid ) THEN 1
ELSE #i+1
END AS rank , id,userid, datetime2 ,#userid:=userid AS clset
from tblName x,(SELECT #i:=0) a ,(SELECT #userid:= 0) s
order by x.userid, datetime2 desc) T
where T.rank='50') ;
Another option:
Use the select query to select the rank <=50 and insert into a new table. Delete the old table and rename the new table afterwards.
insert into newtable (userid,activity,datetime2)
select userid,datetime2 from (
select #i := CASE WHEN ( #userid <> userid ) THEN 1
ELSE
#i+1
END AS rank , userid, activity,datetime2 ,#userid:=userid AS clset
from tblName x,(SELECT #i:=0) a ,(SELECT #userid:= 0) s
order by x.userid, datetime2 desc) T
where t.rank <=50