I am trying to modify a query which results in 2 records before the modification for some reason my modification makes it not work as it return nothing.
This Query works and returns 2 record:
$query = mysql_query("SELECT * FROM `table1`
WHERE `date` = '{$eventdate->format('Y-m-d')}'
OR `date` >= CURDATE() ORDER BY id DESC");
...the I added this: JOIN table2 USING(id)
...so this final code is this:
$query = mysql_query("SELECT * FROM `table1` JOIN `table2` USING(id)
WHERE `date` = '{$eventdate->format('Y-m-d')}'
OR `date` >= CURDATE() ORDER BY id DESC");
Problem is the second one returns nothing.
Is this a syntax error? How can I get this to work? Both tables have id fields.
Make sure that table2 contains matched data, where the id is equal to the id in table1.
You can use a LEFT JOIN if this match is not required.
id in your ORDER BY is now ambiguous. There might be more errors though. Check with mysql_error()
Try This
$query = mysql_query("SELECT * FROM `table1` a,`table2` b WHERE a.id=b.id
and (`a.date` = '{$eventdate->format('Y-m-d')}' OR `a.date` >= CURDATE())
ORDER BY id DESC")
When joining two tables which have no prefixes on the column names like - table1_id, table2_id, you should use aliases like -
SELECT * FROM table1 as t1 JOIN table2 as t2 on ...
and then you can refer to the fields in the table like this - t1.id, t2.id (you can do this also without aliases( as t1) and then you should refer to the fields like - table1.id).
The problem with your script is that the 2 tables have column id and in :
ORDER BY id DESC
the engine doesn`t know from which table do you refer this id
Other suggestion of mine is when possible not to use aggregation functions in the queries(in your query the CURDATE is that type of function). Aggregation functions in SQL prevent query caching. In our case you can pass the currdate from php to the query and the query can be cached.
Hope i`ve helped.
Related
I know this involves JOINS but I can't seem to find a working solution to what I'm trying to do.
I have 2 custom tables :
table1 | table2
---------------------
id id
uid uid
track_id track_id
date date
art active
info
blah
blah2
First I want to select everything WHERE uid=55 AND active=1 from table2 :
$tracks = $wpdb->get_results( "SELECT * FROM table2 WHERE uid = 55 AND active = 1");
And then match the track_id from table2 with results from table1 so I can traverse the table1 data.
I know I can do it like this :
foreach( $tracks as $track ) {
$this_track = $track->track_id;
$results = $wpdb->get_results( "SELECT * FROM table1 WHERE track_id = $this_track");
// Do stuff here
}
But this is the part where it gets tricky...
I then want to ORDER the $results from table1 by date DESC from table2
And this is where I'm lost...
Effectively I want (pseudo code) :
$results = $wpdb->get_results( "SELECT * FROM table1 WHERE track_id = $this_track" ORDER BY date DESC FROM table2);
As well as that last bit, I know I can do this entire routine with JOINS to keep this all in one query and make it way more efficient but I just don't know how.
So just to be clear, my overall routine should be like this :
Get all instances of track_id from table2 where user_id=55 and active=1, then use those results to match the track_id to every result in table1 with the same track_id and then sort the results by date back over from table2
Psuedo code, I know it contains nonsense :
$finalresults = $wpdb->get_results( "SELECT * FROM table2 where uid=55 AND active=1 THEN SELECT * FROM table1 WHERE track_id = "the track_id from the first query" THEN ORDER BY date DESC FROM table2);
Try with this query
SELECT t1.* ,t2.date AS t2date, t2.active FROM table2 AS t2 INNER JOIN table1 AS t1 ON (t1.track_id = t2.track_id) WHERE t2.uid=55 AND t2.active=1 ORDER BY t2.date DESC;
Edit: Explanation of what this query is doing. and inverted the order of the tables retrieved in the query (this don't affect the final datatset, i did this to make to follow the logic of the explanation.
1.- Begin with retrieving all rows from table2 (theres is no specific reason because i used table2 over table1, I'm only following an logical order), using the criteria that you specified iud=55 and active=1
SELECT * FROM table2 WHERE uid=55 AND active=1;
2.- but as you said you need to expand the data retrieved in table2 with some information in table1, that's exactly what it is the directive JOIN made, and we are using INNER JOIN because this type of JOIN will show rows ONLY if data for the uid=55 is present on table1, if there is NO data for the uid=55 present on both TABLES then mysql wil show empty the recordset (0 Rows selected).
in the ON(...) part I specify which criteria mysql will use to compara both tables for match in this case will compare that track_id on table2 it is the same that the specified on table1, if this codition is met then mysql considers it as a match.
anly for convenience and because i'm adding a Second table i gave an Alias to each one t1 and t2.
then the query now seems like this
SELECT * FROM table2 AS t2 INNER JOIN table1 AS t1 ON(t1.track.id = t2.track_id) WHERE t2.uid=55 AND t2.active=1;
3.- but then raise a problem, both tables has rows with the same field names, and this is something that DBMS don't like in their queries, to avoid this situation in the query i only show the fields (id, uid and track_id) from one table in this case t1 (t1.*) and only show the fields that doesn't have this problem from t2 (t2.date AS t2date, t2.active). in this way mysql won't throw any error.
SELECT t1.* ,t2.date AS t2date, t2.active FROM table2 AS t2 INNER JOIN table1 AS t1 ON (t1.track_id = t2.track_id) WHERE t2.uid=55 AND t2.active=1;
4.- for the final step i specify to mysql that i want all found rows ordered descent by a field in the table2;
ORDER BY t2.date DESC;
then this criteria will be applied to the whole selected rows. and the final query has this form.
SELECT t1.* ,t2.date AS t2date, t2.active FROM table2 AS t2 INNER JOIN table1 AS t1 ON (t1.track_id = t2.track_id) WHERE t2.uid=55 AND t2.active=1 ORDER BY t2.date DESC;
if is not completely clear you can ask ...
can i use aggregation function (LAST) in mysql??
if yes then why give me error for following query::
SELECT `user_id`,last(`value`)
FROM `My_TABLE`
group by `user_id`
ERROR:: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(value) FROM My_TABLE group by user_id' at line 1
EDIT:: I got answer "last" is not used in MySql. then How to perform it in MySql??
No, There is nothing called LAST in mysql
See the list of aggregated function
EDIT
You can perform the same something like this
select f.user_id, f.value
from (
select MAX(value) as maxval
from my_table group by user_id
) as x inner join my_table as f on f.value = x.maxval
Something like this -
SELECT * FROM table1 t1
JOIN (SELECT depno, MAX(id) max_id FROM table1 GROUP BY depno) t2
ON t1.depno = t2.depno AND t1.id = t2.max_id
There is no "last" function defined in MySQL. Are you just trying to get the last (newest) record?
If so:
SELECT `user_id`, `value`
FROM `My_TABLE`
ORDER BY `user_id` DESC
LIMIT 1;
or
SELECT `user_id`, `value`
FROM `My_TABLE`
WHERE `user_id` = (SELECT MAX(`user_id`));
Because there is no such function called as last() in mysql..
Try to use group, order by clause in mysql
The best way I found how to handle this:
SELECT user_id, json_unquote(json_extract(json_objectagg('value', value), '$.value'))
FROM my_table
GROUP BY user_id
Can anyone advise on what im doing wrong here?
I am trying to select a table full of results, some are duplicates, but the timestamp is different, so I want to filter out by the latest date.
I'm using the following sql query but it just keeps throwing up errors?
$sql = "(SELECT *
FROM measrate
WHERE TRANS_TIME = (SELECT MAX(TRANS_TIME) FROM measrate)";
First, the initial parenthesis should be unnecessary:
SELECT m.*
FROM measrate m
WHERE TRANS_TIME = (SELECT MAX(TRANS_TIME) FROM measrate m2);
Second, if you want only the max time for some group -- say based on the column result -- then modify this to be a correlated subquery:
SELECT m.*
FROM measrate m
WHERE TRANS_TIME = (SELECT MAX(TRANS_TIME) FROM measrate m2 WHERE m2.result= m.result);
sql = "(SELECT * FROM measrate WHERE TRANS_TIME = (SELECT MAX(TRANS_TIME) FROM measrate))";
Forgot last bracket
I'm trying to get the last ID# from the table called address_contact and the code I use is:
$result = mysql_query("SELECT id FROM address_contact ORDER BY lastUpdate DESC LIMIT 1")
or die(mysql_error());
$row = mysql_fetch_array( $result );
$id = .$row['id'];
Now I would like to close that connection and open a new one and then get all of the data from the following 3 tables using that ID# that we just got:
Table 1: address_address
Table 2: address_contact
Table 3: address_email
so it would look something like this ???
$result = mysql_query("SELECT address_contact.id,address_contact.lastname,address_contact.firstname,address_contact.primaryAddType,address_address.id,address_address.phone1,address_address.phone2,address_address.line2,address_email.id,address_email.email
FROM address_address
LEFT JOIN address_contact ON address_address.id=address_contact.id
LEFT JOIN address_email ON address_address.id=address_email.id
WHERE address_contact.id = ".$id)
But there has to be a easier/faster way of doing this?
If this ID is for a brand new record you'd just inserted, you should be using the msyql_last_insert_id() function, which guarantees that you get the last insert THIS particular script/database handle did. Your method is subject to race conditiosn - if some OTHER script does an insert behind this script's back, you'll get that script's ID, not yours.
That being said, you would be better off doing
SELECT max(id) FROM yourtable
instead of the order by/limit version. It's more efficient to it this way.
The basic code sequence would be:
INSERT INTO yourtable ....
SELECT #id := last_insert_id();
SELECT ... FROM yourtable WHERE id = #id;
You can do this in a single SQL statement using a sub query to find the ID.
SELECT
address_contact.id,
address_contact.lastname,
address_contact.firstname,
address_contact.primaryAddType,
address_address.id,
address_address.phone1,
address_address.phone2,
address_address.line2,
address_email.id,
address_email.email
FROM
address_address
LEFT JOIN address_contact ON address_address.id = address_contact.id
LEFT JOIN address_email ON address_address.id = address_email.id
WHERE address_contact.id = (
SELECT id FROM address_contact ORDER BY lastUpdate DESC LIMIT 1
)
Why not use single query
SELECT address_contact.id,address_contact.lastname,address_contact.firstname,address_contact.primaryAddType,address_address.id,address_address.phone1,address_address.phone2,address_address.line2,address_email.id,address_email.email
FROM address_address
LEFT JOIN address_contact ON address_address.id=address_contact.id
LEFT JOIN address_email ON address_address.id=address_email.id
ORDER BY address_contact.lastUpdate DESC
LIMIT 1
I have a bit of a situation here.
I have a query:
SELECT DISTINCT (testrecurring.id), testrecurring.cxl, testci.cd
FROM testci, testrecurring
WHERE (testci.id = testrecurring.id)
AND testci.x_origin='1'
ORDER BY testrecurring.id DESC;
Now, if a var is not set, I need to do a select on this query, and here is the catch. I need to exclude some id's. Here is how I'm doing it now.
I create a table with that query: create table xxx SELECT * ..... and now the results from my previous query are inside another table called xxx.
Then:
if (!isset($var)) {
$delete = mysql_query("delete from xxx USING xxx, future_recurring where xxx.id = future_recurring.id");
}
and after the records have been deleted I do my final select * from xxx.
This works just fine, the only thing is that I need to redo all this logic by not creating any tables. Maybe doing some joins, I'm not sure how to proceed.
I hope this is not very confusing.
Any ideas?
And now how about this?:
SELECT tr.id, tr.cxl, tci.cd
FROM testci AS tci
INNER JOIN testrecurring AS tr
ON tci.id = tr.id
LEFT OUTER JOIN future_recurring AS fr
ON tr.id = fr.id
WHERE tci.x_origin='1'
AND fr.id IS NULL
GROUP BY tr.id, tr.cxl, tci.cd
ORDER BY tr.id DESC
This only includes results in which the testrecurring.id is NOT FOUND in future_recurring
You just need to add a where condition to exclude the rows you don't want:
SELECT *
FROM testci
JOIN testrecurring on testrecurring.id = testci.id
WHERE testci.x_origin='1'
AND testci.id NOT IN (SELECT id FROM future_recurring)
ORDER BY testrecurring.id DESC;
Or you could try this which might give better performance:
SELECT *
FROM testci
JOIN testrecurring on testrecurring.id = testci.id
LEFT JOIN future_recurring on future_recurring.id = testci.id
WHERE testci.x_origin='1'
AND future_recurring id IS null
ORDER BY testrecurring.id DESC;
Although, if your indexes are good and sane and your data sets aren't enormous then the performance should be close.