I'm moving a few boolean columns from the 1st row of a generic settings table into the 1st row of a website_settings table across a few MYSQL databases. I've created the new columns in my new table with a default false value.
I have a working query to copy data from the old table:
UPDATE website_settings
SET
dark_mode_enabled = (SELECT dark_mode_enabled FROM settings ORDER BY id LIMIT 1),
header_enabled = (SELECT header_enabled FROM settings ORDER BY id LIMIT 1),
footer_enabled = (SELECT footer_enabled FROM settings ORDER BY id LIMIT 1)
LIMIT 1;
However for my own knowledge, I'm curious if there is a more cleaner way to write this, perhaps without the repetitive select queries to the same table?
You could use a join:
UPDATE website_settings ws CROSS JOIN
(SELECT s.*
FROM settings s
ORDER id DESC
LIMIT 1
) s
SET ws.dark_mode_enabled = s.dark_mode_enabled,
ws.header_enabled = s.header_enabled,
ws.footer_enabled = s.footer_enabled
LIMIT 1;
Here's a solution that does not use JOIN:
INSERT INTO website_settings (id, dark_mode_enabled, header_enabled, footer_enabled)
SELECT id, dark_mode_enabled, header_enabled, footer_enabled
FROM settings ORDER BY id LIMIT 1
ON DUPLICATE KEY UPDATE
dark_mode_enabled = VALUES(dark_mode_enabled),
header_enabled = VALUES(header_enabled),
footer_enabled = VALUES(footer_enabled);
I have a requirement to update the first 8 rows in a table each time the page refreshes.
The way I have tried to approach this is using the query below but it updates all the rows in the table.
Can anyone see where I am going wrong or is there a better way to do this.
$query_conf_update = "
UPDATE ConfBookings2017
Set Screen1
WHERE HotelID ='".$HotelID."'
AND RecordID IN (
SELECT RecordID FROM (
SELECT RecordID
FROM ConfBookings2017
WHERE HotelID ='".$HotelID."'
ORDER
BY RoomFromTime DESC
LIMIT 0, 8
) tmp
)";
Single-table UPDATE allows ORDER BY and LIMIT, so subquery is excess:
UPDATE ConfBookings2017
Set Screen1 = 'new value' /* or parameter placeholder */
WHERE HotelID ='".$HotelID."' /* recommendation - convert to parameter */
/* AND another conditions, for example, Screen1 != 'new value' */
ORDER BY RoomFromTime DESC
LIMIT 8;
I have a table with 3 columns, as follows:
Columns:
ID
Channel_Location
Used
I would like to retrieve a random entry from the table and update Used column to 1. However, when I run my code - shown below - it returns 0 rows and doesn't return any idea. I was wondering why is this case?
The code
UPDATE channels
SET Used = 1
WHERE ID IN (
SELECT ID
FROM (select ID
FROM channels
WHERE Used != 0
ORDER BY RAND()
LIMIT 1) x);
One way to address this issue, is to do as follows:
SET #uid := (SELECT ID FROM channels WHERE Used = 0 ORDER BY RAND() LIMIT 1);
UPDATE channels SET Used = 1 WHERE ID = #uid;
SELECT * FROM channels WHERE ID = #uid;
Query 1:
set #userName = 'harry';
set #previousRegionId = (
select Region as RegionID
from log
where User = #userName
order by stamp desc
limit 1);
select #previousRegionId;
Query 2:
set #previousRegionId = (
select Region as RegionID
from log
where User = 'harry'
order by stamp desc
limit 1);
select #previousRegionId;
I expect the same result for both queries, but the result is different and it is reproduceable!
The log table contains same value in User column for all rows ('harry').
Changed the order by clause. Order by id works "better". Order by timestamp column is suspect ...
I am not 100% sure if this approach will work in all scenarios/aspects.
I'd like to use a single SQL query (in MySQL) to find the record which comes after one that I specify.
I.e., if the table has:
id, fruit
-- -----
1 apples
2 pears
3 oranges
I'd like to be able to do a query like:
SELECT * FROM table where previous_record has id=1 order by id;
(clearly that's not real SQL syntax, I'm just using pseudo-SQL to illustrate what I'm trying to achieve)
which would return:
2, pears
My current solution is just to fetch all the records, and look through them in PHP, but that's slower than I'd like. Is there a quicker way to do it?
I'd be happy with something that returned two rows -- i.e. the one with the specified value and the following row.
EDIT: Sorry, my question was badly worded. Unfortunately, my definition of "next" is not based on ID, but on alphabetical order of fruit name. Hence, my example above is wrong, and should return oranges, as it comes alphabetically next after apples. Is there a way to do the comparison on strings instead of ids?
After the question's edit and the simplification below, we can change it to
SELECT id FROM table WHERE fruit > 'apples' ORDER BY fruit LIMIT 1
SELECT * FROM table WHERE id > 1 ORDER BY id LIMIT 1
Even simpler
UPDATE:
SELECT * FROM table WHERE fruit > 'apples' ORDER BY fruit LIMIT 1
So simple, and no gymnastics required
Select * from Table
where id =
(Select Max(id) from Table
where id < #Id)
or, based on the string #fruitName = 'apples', or 'oranges' etc...
Select * from Table
where id =
(Select Max(id) from Table
where id < (Select id from Table
Where fruit = #fruitName))
I'm not familiar with the MySQL syntax, but with SQL Server you can do something with "top", for example:
SELECT TOP 1 * FROM table WHERE id > 1 ORDER BY id;
This assumes that the id field is unique. If it is not unique (say, a foreign key), you can do something similar and then join back against the same table.
Since I don't use MySQL, I am not sure of the syntax, but would imagine it to be similar.
Unless you specify a sort order, I don't believe the concepts of "previous" or "next" are available to you in SQL. You aren't guaranteed a particular order by the RDBMS by default. If you can sort by some column into ascending or descending order that's another matter.
This should work. The string 'apples' will need to be a parameter.
Fill in that parameter with a string, and this query will return the entire record for the first fruit after that item, in alphabetical order.
Unlike the LIMIT 1 approach, this should be platform-independent.
--STEP THREE: Get the full record w/the ID we found in step 2
select *
from
fruits fr
,(
--STEP TWO: Get the ID # of the name we found in step 1
select
min(vendor_id) min_id
from
fruits fr1
,(
--STEP ONE: Get the next name after "apples"
select min(name) next_name
from fruits frx
where frx.name > 'apples'
) minval
where fr1.name = minval.next_name
) x
where fr.vendor_id = x.min_id;
The equivalent to the LIMIT 1 approach in Oracle (just for reference) would be this:
select *
from
(
select *
from fruits frx
where frx.name > 'apples'
order by name
)
where rownum = 1
I don't know MySQL SQL but I still try
select n.id
from fruit n
, fruit p
where n.id = p.id + 1;
edit:
select n.id, n.fruitname
from fruits n
, fruits p
where n.id = p.id + 1;
edit two:
Jason Lepack has said that that doesn't work when there are gaps and that is true and I should read the question better.
I should have used analytics to sort the results on fruitname
select id
, fruitname
, lead(id) over (order by fruitname) id_next
, lead(fruitname) over (order by fruitname) fruitname_next
from fruits;
If you are using MS SQL Server 2008 (not sure if available for previous versions)...
In the event that you are trying to find the next record and you do not have a unique ID to reference in an applicable manner, try using ROW_NUMBER(). See this link
Depending on how savvy your T-SQL skill is, you can create row numbers based on your sorting order. Then you can find more than just the previous and next record. Utilize it in views or sub-queries to find another record relative to the current record's row number.
SELECT cur.id as id, nxt.id as nextId, prev.id as prevId FROM video as cur
LEFT JOIN video as nxt ON nxt.id > cur.id
LEFT JOIN video as prev ON prev.id < cur.id
WHERE cur.id = 12
ORDER BY prev.id DESC, nxt.id ASC
LIMIT 1
If you want the item with previous and next item this query lets you do just that.
This also allows You to have gaps in the data!
How about this:
Select * from table where id = 1 + 1