I've been googling around and can't seem to find how to fix this. I'm currently using MySQL and am trying to run this
SELECT song_id FROM ‘played_songs’ WHERE id=MAX(id)
When I run this, I get the error message
1111 - Invalid use of group function
Does anyone know what I am doing wrong here? For reference, I'm trying to get the latest row's song_id in a pre-existing database. The ID increments so the latest value is the max ID in the column. When I get that column, I would like to get it's song_id in that same row.
Sorry if this is a super basic question, I've never done this before.
Thanks!
you can't use max in where clause, try this:
SELECT song_id FROM played_songs WHERE id=(SELECT max(id) FROM played_songs)
but better solution is:
SELECT song_id FROM played_songs ORDER BY id DESC LIMIT 1;
You need to use a "Having" instead of a "where". A Having is used when you are operating on a previous calculation (getting max id is a calculation mysql has to make). I would write like this.
SELECT song_id, MAX(id) as
max_id FROM ‘played_songs’
HAVING max_id=id
I am wondering if there is away (possibly a better way) to order by the order of the values in an IN() clause.
The problem is that I have 2 queries, one that gets all of the IDs and the second that retrieves all the information. The first creates the order of the IDs which I want the second to order by. The IDs are put in an IN() clause in the correct order.
So it'd be something like (extremely simplified):
SELECT id FROM table1 WHERE ... ORDER BY display_order, name
SELECT name, description, ... WHERE id IN ([id's from first])
The issue is that the second query does not return the results in the same order that the IDs are put into the IN() clause.
One solution I have found is to put all of the IDs into a temp table with an auto incrementing field which is then joined into the second query.
Is there a better option?
Note: As the first query is run "by the user" and the second is run in a background process, there is no way to combine the 2 into 1 query using sub queries.
I am using MySQL, but I'm thinking it might be useful to have it noted what options there are for other DBs as well.
Use MySQL's FIELD() function:
SELECT name, description, ...
FROM ...
WHERE id IN([ids, any order])
ORDER BY FIELD(id, [ids in order])
FIELD() will return the index of the first parameter that is equal to the first parameter (other than the first parameter itself).
FIELD('a', 'a', 'b', 'c')
will return 1
FIELD('a', 'c', 'b', 'a')
will return 3
This will do exactly what you want if you paste the ids into the IN() clause and the FIELD() function in the same order.
See following how to get sorted data.
SELECT ...
FROM ...
WHERE zip IN (91709,92886,92807,...,91356)
AND user.status=1
ORDER
BY provider.package_id DESC
, FIELD(zip,91709,92886,92807,...,91356)
LIMIT 10
Two solutions that spring to mind:
order by case id when 123 then 1 when 456 then 2 else null end asc
order by instr(','||id||',',',123,456,') asc
(instr() is from Oracle; maybe you have locate() or charindex() or something like that)
If you want to do arbitrary sorting on a query using values inputted by the query in MS SQL Server 2008+, it can be done by creating a table on the fly and doing a join like so (using nomenclature from OP).
SELECT table1.name, table1.description ...
FROM (VALUES (id1,1), (id2,2), (id3,3) ...) AS orderTbl(orderKey, orderIdx)
LEFT JOIN table1 ON orderTbl.orderKey=table1.id
ORDER BY orderTbl.orderIdx
If you replace the VALUES statement with something else that does the same thing, but in ANSI SQL, then this should work on any SQL database.
Note:
The second column in the created table (orderTbl.orderIdx) is necessary when querying record sets larger than 100 or so. I originally didn't have an orderIdx column, but found that with result sets larger than 100 I had to explicitly sort by that column; in SQL Server Express 2014 anyways.
SELECT ORDER_NO, DELIVERY_ADDRESS
from IFSAPP.PURCHASE_ORDER_TAB
where ORDER_NO in ('52000077','52000079','52000167','52000297','52000204','52000409','52000126')
ORDER BY instr('52000077,52000079,52000167,52000297,52000204,52000409,52000126',ORDER_NO)
worked really great
Ans to get sorted data.
SELECT ...
FROM ...
ORDER BY FIELD(user_id,5,3,2,...,50) LIMIT 10
The IN clause describes a set of values, and sets do not have order.
Your solution with a join and then ordering on the display_order column is the most nearly correct solution; anything else is probably a DBMS-specific hack (or is doing some stuff with the OLAP functions in standard SQL). Certainly, the join is the most nearly portable solution (though generating the data with the display_order values may be problematic). Note that you may need to select the ordering columns; that used to be a requirement in standard SQL, though I believe it was relaxed as a rule a while ago (maybe as long ago as SQL-92).
Use MySQL FIND_IN_SET function:
SELECT *
FROM table_name
WHERE id IN (..,..,..,..)
ORDER BY FIND_IN_SET (coloumn_name, .., .., ..);
For Oracle, John's solution using instr() function works. Here's slightly different solution that worked -
SELECT id
FROM table1
WHERE id IN (1, 20, 45, 60)
ORDER BY instr('1, 20, 45, 60', id)
I just tried to do this is MS SQL Server where we do not have FIELD():
SELECT table1.id
...
INNER JOIN
(VALUES (10,1),(3,2),(4,3),(5,4),(7,5),(8,6),(9,7),(2,8),(6,9),(5,10)
) AS X(id,sortorder)
ON X.id = table1.id
ORDER BY X.sortorder
Note that I am allowing duplication too.
Give this a shot:
SELECT name, description, ...
WHERE id IN
(SELECT id FROM table1 WHERE...)
ORDER BY
(SELECT display_order FROM table1 WHERE...),
(SELECT name FROM table1 WHERE...)
The WHEREs will probably take a little tweaking to get the correlated subqueries working properly, but the basic principle should be sound.
My first thought was to write a single query, but you said that was not possible because one is run by the user and the other is run in the background. How are you storing the list of ids to pass from the user to the background process? Why not put them in a temporary table with a column to signify the order.
So how about this:
The user interface bit runs and inserts values into a new table you create. It would insert the id, position and some sort of job number identifier)
The job number is passed to the background process (instead of all the ids)
The background process does a select from the table in step 1 and you join in to get the other information that you require. It uses the job number in the WHERE clause and orders by the position column.
The background process, when finished, deletes from the table based on the job identifier.
I think you should manage to store your data in a way that you will simply do a join and it will be perfect, so no hacks and complicated things going on.
I have for instance a "Recently played" list of track ids, on SQLite i simply do:
SELECT * FROM recently NATURAL JOIN tracks;
I've encountered this problem for a while and I can't seem to find the right answer on google. I don't know if maybe I'm just unlucky.
Anyway, how can I get row number from a specific record I input from a PHP text field, for example:
ID NAME
11111 john
11112 roger
11113 ellis
11114 jack
11115 wendy
So if I input 11113, the output will be like "this ID is at number 3".
Here is my code:
$id=$_POST['id'];
$query="SELECT COUNT(*) from employee where id like '%$id%'";
$num=mysql_query($query);
echo "this ID is at number $num";
Can anyone point out where did I go wrong?
Here is a query example of how you can do it without adding another column for count:
SELECT e.*,b.count FROM employee as e, (SELECT COUNT(*) as count FROM employee WHERE id <= 3) as b WHERE e.id = 3
Using another select query to count all the rows with id smaller than the id requested
Or if you only want the offset of the row without its data:
SELECT COUNT(*) as count FROM employee WHERE id <= 3
At first, you should select * from the employee table
Then parse the result to array,
Scan the above array (step2) and find your value (11113)
If (3) is found, then you can return array index.
First thing:
You're using old PHP-method for database, use PDO
If you wan't to get the last insert ID, it's possible to catch it with PDO
And I don't understand your SQL, because you want to get an ID, by filtering with the ID? And when your ID is an INTEGER/NUMBER, than your statement is senseless.
I just took a dive into Mysql, I have following tables:
items,table1
Items contain item_name and id and table1 contain name, item_id , value
Now I have to look browse in such a way that it will give like:
name1-item_id-sum(value)
name2-item_id-sum(value)
name3-item_id-sum(value)
name4-item_id-sum(value)
name5-item_id-sum(value)
I tried to search double group by but none worked... Please help me as soon as possible.
Uhm. I think, this might help.
You don't need to use item table because at the first place, you're not getting any help from it.
mysql_query("SELECT name, item_id, SUM(value) FROM table1 GROUP BY item_id, name");
ADD: use ORDER BY name DESC for much formal result.
I need to get the ID (a column) from the last row inserted, in a table. I'm wondering if there's any way to somehow embed that in another query, to avoid having two different querys? It seems much simpler, and i believe i've seen it somewhere before.
Something like this:
$query = "INSERT INTO a_table (x, y) VALUES ((SELECT id FROM another_table ORDER BY id DESC), 'y...')";
Any ideas how to do that?
Thanks.
If you're looking to get the newest record created by your script, you should never do it this way in the first place. What if another instance of your script created a record at the same time?
mySQL's LAST_INSERT_ID() will return the last ID created over this specific connection. However, you must call it immediately after your insert statement.
If getting the highest ID is literally what you want, GSto's answer will work for you.
INSERT INTO a_table (x, y) VALUES (SELECT max(id), 'y...' FROM another_table);
Yes, MySQL has an INSERT .. SELECT statement:
example:
INSERT INTO a_table (x,y) SELECT id,'y' FROM another_table ORDER BY id DESC
although keep in mind, unless you have an auto_incrementing ID field, the order by clause is pointless here.