Is it not possible to do an Operation like this in an SQL Statement?
INSERT INTO ships (user_id,construction_time, fleet_id, template_id, experience, hitpoints,unit_4,rof)
VALUES (11, UNIX_TIMESTAMP(), (-5002), (SELECT id, value_9, value_5, min_unit_4, rof FROM ship_templates WHERE ship_torso >2 ORDER BY RAND() LIMIT 1))
Copy one table data to another :-
INSERT INTO TARGET_TABLE (`col1`,`col2`) SELECT `col1`,`col2` FROM SOURCE_TABLE;
Try this:-
INSERT INTO ships (ser_id,construction_time, fleet_id, template_id, experience, hitpoints,unit_4,rof)
SELECT '11',UNIX_TIMESTAMP(),(-5002),id, value_9, value_5, min_unit_4, rof FROM ship_templates WHERE ship_torso >2 ORDER BY RAND() LIMIT 1;
Related
I am trying to do an insert select but require some aliased values for calculations but don't need all of them for my insert. I just need field0, total_sum, hard_coded_val but rely on the others for the calculations.
is there any way to either ignore the other values or specify the VALUES() in the insert SELECT?
INSERT INTO table(field0,total_sum,hard_coded_val)
SELECT s.*, sum1+sum2 AS total_sum, 'hard_coded_val' FROM
(SELECT t.*, (fielda+fieldb)*2 AS sum1, (fieldc+fieldd)/4 AS sum2 from
(SELECT field0,
sum(IF(field1 = 1, totalcount,0)) AS fielda,
sum(IF(field1 = 2, totalcount,0)) AS fieldb,
sum(IF(field1 = 3, totalcount,0)) AS fieldc,
sum(IF(field1 = 4,totalcount,0)) AS fieldd
from source_table GROUP BY field0)
t ORDER BY sum1 DESC)
s ORDER BY total_sum DESC
You just need to limit the number of columns you're returning. * will return all columns for the table associated with it.
INSERT INTO table(field0,total_sum,hard_coded_val)
SELECT s.field0, sum1+sum2 AS total_sum, 'hard_coded_val' FROM
...
here i am trying to insert patient_id and nurse_id which are from two different tables.
insert into nurse_take_care(patient_id,nurse_id) values (patient_id(select MAX(p_id) from patient;), nurse_id(Select n_id from nurse order by Rand() limit 1;))
is this the right way to do??
The query would be like:
insert into nurse_take_care(patient_id,nurse_id) values
(select MAX(p_id) from patient limit 1, Select n_id from nurse order by Rand() limit 1);
Please try this insert into nurse_take_care(patient_id,nurse_id)
SELECT (select MAX(p_id) from patient) as p_id, (select n_id from nurse order by Rand() limit 1) as n_id
Try something like this:
INSERT INTO nurse_take_care (patient_id, nurse_id)
SELECT ( SELECT MAX(p_id) FROM patient ),
( SELECT n_id FROM nurse ORDER BY RAND() LIMIT 1 )
I want to insert into a table using a select statement as well as a unique value. The following query returns an error that the column counts are not matching. What am I missing?
insert into moving_average (ma_symbol, ma_date, ma5)
values
(
select 'A', max(temp.histDate), avg(temp.histClose)
from
(
select hd.histDate, hd.histClose
from historical_data hd
where symbol like 'A' order by hd.histDate asc limit 5
) temp
);
Try this:
insert into moving_average (ma_symbol, ma_date, ma5)
select 'A', max(histDate), avg(histClose)
from (select (histDate), (histClose)
from historical_data
where symbol like 'A'
order by histDate asc
limit 5) temp;
INSERT INTO ... SELECT statement does not use VALUES keyword.
I am trying to find a datetime value in a mysql database that is the closest match to a datetime that i specify, i am having some trouble.
The following pseudo code is what i want to achieve:
SELECT one FROM table WHERE datetimefield is closest to "2014-12-10 09:45:00" LIMIT 1
The key idea is to use order by and limit:
If you want the closest one before:
SELECT one
FROM table
WHERE datetimefield <= '2014-12-10 09:45:00'
ORDER BY datetimefield DESC
LIMIT 1;
If you want the closest, in either direction, then use TIMESTAMPDIFF():
ORDER BY abs(TIMESTAMPDIFF(second, datetimefield, '2014-12-10 09:45:00'))
LIMIT 1
Using abs() prevents using a datetimefield index. I propose to have one select for the closest before and one select for the closest after, both using the index, and picking the closest of them afterwards:
create table `table` (datetimefield datetime key, one varchar(99));
insert into `table` values
('2014-06-01', 'a'), ('2014-12-01', 'b'),
('2015-01-01', 'c'), ('2015-02-01', 'd');
set #d = '2014-12-10 09:45:00';
select * from
(
( select *, TIMESTAMPDIFF(SECOND, #d, datetimefield) as diff
from `table` where datetimefield >= #d
order by datetimefield asc limit 1
)
union
( select *, TIMESTAMPDIFF(SECOND, datetimefield, #d) as diff
from `table` where datetimefield < #d
order by datetimefield desc limit 1
)
) x
order by diff
limit 1;
http://sqlfiddle.com/#!2/bddb4/1
Use ABS()
SELECT one FROM table
ORDER BY ABS(`datetimefield` - '2014-12-10 09:45:00') LIMIT 1
This will return the row with lowest difference, that is closest.
Let's say I was looking for the second most highest record.
Sample Table:
CREATE TABLE `my_table` (
`id` int(2) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`value` int(10),
PRIMARY KEY (`id`)
);
INSERT INTO `my_table` (`id`, `name`, `value`) VALUES (NULL, 'foo', '200'), (NULL, 'bar', '100'), (NULL, 'baz', '0'), (NULL, 'quux', '300');
The second highest value is foo. How many ways can you get this result?
The obvious example is:
SELECT name FROM my_table ORDER BY value DESC LIMIT 1 OFFSET 1;
Can you think of other examples?
I was trying this one, but LIMIT & IN/ALL/ANY/SOME subquery is not supported.
SELECT name FROM my_table WHERE value IN (
SELECT MIN(value) FROM my_table ORDER BY value DESC LIMIT 1
) LIMIT 1;
Eduardo's solution in standard SQL
select *
from (
select id,
name,
value,
row_number() over (order by value) as rn
from my_table t
) t
where rn = 1 -- can pick any row using this
This works on any modern DBMS except MySQL. This solution is usually faster than solutions using sub-selects. It also can easily return the 2nd, 3rd, ... row (again this is achievable with Eduardo's solution as well).
It can also be adjusted to count by groups (adding a partition by) so the "greatest-n-per-group" problem can be solved with the same pattern.
Here is a SQLFiddle to play around with: http://sqlfiddle.com/#!12/286d0/1
This only works for exactly the second highest:
SELECT * FROM my_table two
WHERE EXISTS (
SELECT * FROM my_table one
WHERE one.value > two.value
AND NOT EXISTS (
SELECT * FROM my_table zero
WHERE zero.value > one.value
)
)
LIMIT 1
;
This one emulates a window function rank() for platforms that don't have them. It can also be adapted for ranks <> 2 by altering one constant:
SELECT one.*
-- , 1+COALESCE(agg.rnk,0) AS rnk
FROM my_table one
LEFT JOIN (
SELECT one.id , COUNT(*) AS rnk
FROM my_table one
JOIN my_table cnt ON cnt.value > one.value
GROUP BY one.id
) agg ON agg.id = one.id
WHERE agg.rnk=1 -- the aggregate starts counting at zero
;
Both solutions need functional self-joins (I don't know if mysql allows them, IIRC it only disallows them if the table is the target for updates or deletes)
The below one does not need window functions, but uses a recursive query to enumerate the rankings:
WITH RECURSIVE agg AS (
SELECT one.id
, one.value
, 1 AS rnk
FROM my_table one
WHERE NOT EXISTS (
SELECT * FROM my_table zero
WHERE zero.value > one.value
)
UNION ALL
SELECT two.id
, two.value
, agg.rnk+1 AS rnk
FROM my_table two
JOIN agg ON two.value < agg.value
WHERE NOT EXISTS (
SELECT * FROM my_table nx
WHERE nx.value > two.value
AND nx.value < agg.value
)
)
SELECT * FROM agg
WHERE rnk = 2
;
(the recursive query will not work in mysql, obviously)
You can use inline initialization like this:
select * from (
select id,
name,
value,
#curRank := #curRank + 1 AS rank
from my_table t, (SELECT #curRank := 0) r
order by value desc
) tb
where tb.rank = 2
SELECT name
FROM my_table
WHERE value < (SELECT max(value) FROM my_table)
ORDER BY value DESC
LIMIT 1
SELECT name
FROM my_table
WHERE value = (
SELECT min(r.value)
FROM (
SELECT name, value
FROM my_table
ORDER BY value DESC
LIMIT 2
) r
)
LIMIT 1