I wonder if any can help me understand something I'm trying to solve.
I'm working on a wordpress site but this is more a sql question as I'm just querying to get some results within a template file.
I have a gallery of pictures which are advert boxes, and I need to pull these in relation to a supplied movie name, to do this Im using some custom fields on the ad pic called 'adlink' (link off ad) and ad
I'm using the nextgen gallery plugin and querying those tables, and I have three tables in total that contain the data I need to query.
ngg_pictures, nggcf_field_values & nggcf_fields.
the nggcf tables are custom fields tables,
I have got so far I can get what I need in two seperate queries, but I can't combine these into one query as it means querying the nggcf_field_values table twice, which I can't seem to sort.
I have hardcoded the search criteria in for the mo, but the 'close-encounters' bit would be a passed var, and the '156' would be the pid from the first query.
SELECT `eg_ngg_pictures`.`filename`, `eg_nggcf_field_values`.`fid`, `eg_nggcf_field_values`.`pid`
FROM eg_ngg_pictures, eg_nggcf_field_values
WHERE ((`eg_nggcf_field_values`.`field_value` LIKE 'close-encounters') AND (`eg_nggcf_field_values`.`pid` = eg_ngg_pictures.pid))
SELECT `eg_nggcf_field_values`.`field_value`
FROM eg_nggcf_field_values, eg_nggcf_fields
WHERE ((`eg_nggcf_fields`.`field_name` = 'adlink') AND (`eg_nggcf_fields`.`id` = eg_nggcf_field_values.fid) AND (`eg_nggcf_field_values`.`pid` = '156'))
any help would be greatly appreciated, I can get the results with what I have, but I like to understand how to combine these two and write better SQl. Thanks MRO
After looking at the Wordpress extension, I think the eg_nggcf_fields is the table that contains the name for a custom field. The eg_nggcf_field_values table contains the values of that custom field per picture.
So if you're looking for two fields called moviename and adlink, you have to look up two rows in the field_values table. You can join a table twice if you give it a different alias:
select pic.filename
, pic.pid
, fv1.field_value as MovieName
, fv2.field_value as Adlink
from eg_ngg_pictures pic
inner join -- Find ID for the field called 'moviename'
eg_nggcf_fields f1
on f1.field_name = 'moviename'
inner join -- Find value for field moviename for this picture
eg_nggcf_field_values as fv1
on fv1.pid = pic.pid
and fv1.fid = f1.fid
inner join -- Find ID for the field called 'adlink'
eg_nggcf_fields f2
on f2.field_name = 'adlink'
inner join -- Find value for field adlink for this picture
eg_nggcf_field_values as fv2
on fv2.pid = pic.pid
and fv2.fid = f2.fid
where fv1.field_value like 'close-encounters'
First of all, I'd recommend sticking to modern ANSI syntax for JOINing tables, which means using the JOIN clause.
Instead of using:
FROM table1, table2 WHERE table1.id = table2.pid
use:
FROM Table 1 JOIN table2 ON table1.id = table2.id
For simplicity's sake, I'd also recommend you to alias tables, as that tends to make the code more readable. Instead of having to write out egg_ngg_pictures every time, you can simply refer to the alias you assign it instead.
Lastly, when you use a LIKE operator, you usually add a wild-card character (typically %. I.e. LIKE '%123' or LIKE '123%'). You seem to look only for complete matches, which means you can just stick to using =, as that should give you slightly better performance.
Now to rewrite your query, I'd use something like the following:
SELECT
pic.filename
, fieldval.fid
, fieldval.pid
, fieldval.field_value
FROM
eg_ngg_pictures pic
JOIN eg_nggcf_field_values fieldval ON fieldval.pid = pic.pid
JOIN eg_nggcf_fields fields ON fields.id = fieldval.fid
WHERE
((fieldval.field_value = 'close-encounters')
AND fields.field_name = 'ad_link'
Note that I am not able to test the query, as I do not have your schema. But by incorporating the two queries into a single query, the join on the field_Values.PID retreieved with the 'close_encounters' value should already exist.
If the query does not work, feel free to create a SQL fiddle with the relevant tables and some data, and I'll try and get it to work with that.
Related
Situation Overview
The current question is a problem about selecting values from two tables table A (material) and table B (MaterialRevision). However, The PK of table A might or Might not exist in Table B. When it doesnt exists, the query described in this question wont return the values of table A, but IT SHOULD. So basically here's whats happening :
The query is only returning values when A.id exists in B.id, when In fact, I need it to return values from A when A.id ALSO dont exist in B.id.
Problem:
Suppose two tables. Table Material and Table Material Revision.
Notice that the PK idMaterial is a FK in MaterialRevision.
Current "Mock" Tables
Query Objective
Obs: remember these two tables are a simplification of the real
tables.
For each Material, print the material variables and the last(MAX) RevisionDate from MaterialRevision. In case theres no RevisionDate, print BLANK ("") for the "last revision date".
What is wrongly happening
For each Material, print the material variables and the last(MAX) RevisionDate from MaterialRevision. In case theres no Revision for the Material, doesnt print the Material (SKIP).
Current Code
SELECT
Material.idMaterial,
Material.nextRevisionDate,
Material.obsolete,
lastRevisionDate
FROM Material,
(SELECT MaterialRevision.idMaterial, max(MaterialRevision.revisionDate) as "revisionDate" from MaterialRevision
GROUP BY MaterialRevision.idMaterial
) AS Revision
WHERE (Material.idMaterial = Revision.idMaterial AND Material.obsolete = 0)
References and Links used to reach the state described in this question
Why is MAX() 100 times slower than ORDER BY ... LIMIT 1?
MySQL get last date records from multiple
MySQL - How to SELECT based on value of another SELECT
MySQL Query Select where id does not exist in the JOIN table
PS I hope this question is correctly understood since it took me a lot of time to build it. I researched a lot in stackoverflow and after
several failed attempts I had no option but to ask for help.
You should use JOIN :
SELECT m.idMaterial, m.nextRevisionDate, mr.revisionDate AS "lastRevisionDate"
FROM Material m
LEFT JOIN MaterialRevision AS mr ON mr.idMaterial = m.idMaterial AND mr.revisionDate = (
SELECT MAX(ch.revisionDate) from MaterialRevision ch
WHERE mr.idMaterial = ch.idMaterial)
WHERE m.obsolete = 0
Here is an explanation of what INNER JOIN, LEFT JOIN and RIGHT JOIN are. (You will love them if you often cross tables in your queries)
As m.obsolete will always be true, I ommited it in the SELECT clause
You should use the left outer join instead of using the cross product.
You're query should be something like this:
SELECT idMaterial, nextRevisionableDate, obsolete,
revisionDate AS lastRevisionDate
FROM Material
LEFT OUTER JOIN MaterialRevision AS mr On
Material.idMaterial = MaterialRevision.id
AND mr.revisionDate = (SELECT MAX(ch.revisionDate) from MaterialRevision ch
WHERE mr.idMaterial = ch.idMaterial)
WHERE obsolete = 0;
Here you can find some documentation about types of join.
I'm working with a database that is not normalized efficiently so I am having to get creative in joining tables. I have one table that has a column name 'direction_or' with full names like 'Northwest','Southwest' and another table with the same column name but abbreviates them like 'NW','SW' and I am needing to join the tables on those parameters. Joining on keys is not possible unfortunately.
I was wondering if it is possible to use a CASE WHEN or something to evaluate the full name and then make it the abbreviated name then JOINING the tables based on that abbreviated name in one query.
Like I said I'm having to get creative and this has got me stumped.
Something like this, forgive me for my ignorance.
SELECT * FROM user.directions AS A (somehow change the value of A.direction_or AS newAbb) LEFT JOIN stored.directons AS B ON A.newAbb = B.direction_or
Thank you in advance.
If you want an easy yet heavy way, you can :
create a table pairing terms. It should be pretty lightweight and most probably cached everytime you use it, but it still have a weight since imbriqued select.
You would then do :
SELECT * FROM user.directions AS A LEFT JOIN stored.directons AS B ON (select desiredvalue from StatesAndAbreviation where state = A.newAbb) = B.direction_or
or something like this.
And other way to work around this would be to use enums. By creating two enums and mapping corresponding strings to equivalent integers, you could probably compare them quite easily. You need to alter the tables to change the types of the varchar -> corresponding enum.
See:
https://dev.mysql.com/doc/refman/8.0/en/enum.html
Edit: When comparing enums, you would probably have to do something awkward like where A.enumvar+0 = B.enumvar+0. You can still try without it though since the code would be easier to read if it works.
You can create a lookup table which maps full names to abbreviated names, then join with that table in your query.
Else you can also do it this way:
SELECT * FROM
(
SELECT *,
CASE
WHEN direction_or = 'Northwest' THEN 'NW'
WHEN direction_or = 'Southwest' THEN 'SW'
-- all other possibilities here
ELSE ''
END as direction_or_abb
FROM user.directions
) a
JOIN stored.directions b
ON a.direction_or_abb = b.direction_or
Could someone please tell explain to me how to properly process a query that collects information from 2 tables, i thought I had this figured out until I added more records. Please look at the image I have below:enter image description here
(The last record should not have the name "Thomas Murray" in it)
Then there is the query I am processing:
"select a.*, b.forenames, b.surname FROM playerSkills a, playerdb b GROUP BY sheetNo"
What I was hoping to do is collect all from the playerSkills database (which it does) and only bring over the names from the second database (playerdb) that matched with the playerID but as I want to return more than one result so I don't know what to do as it returns the whole column and just pastes the one name into every field.
Though I am sure a JOIN is to be inserted here, I am not sure which or at all.
I am not experienced with SQL but trying to wrap my head around it. I have experimented with the JOIN clauses but didn't get far probably due to a syntax.
How can join the names to the playerID so they appear in the appropriate fields?
You need columns to join on . . . and proper join syntax:
select ps.*, p.forenames, p.surname
FROM playerSkills ps JOIN
playerdb p
ON ps.playerId = p.playerId;
Notes:
Your query does not require GROUP BY.
Your query does require JOIN conditions.
Kudos for using table aliases. They should be abbreviations for the table name.
You want to always use explicit JOIN syntax. No commas in the FROM clause.
How can i use in table field values in the url
SQL Query wherein all 3 tables are joined
select * from nfojm_usedcar_variants cv
inner join nfojm_usedcar_products cp
inner join nfojm_usedcar_categories cc on
cc.id=cp.prod_cat_id and
cp.id=cv.v_prod_id and
cv.state='1' order by cv.id desc
Output as checked
Then it combines all 3 tables
nfojm_usedcar_variants
nfojm_usedcar_products
nfojm_usedcar_categories
However - all 3 tables have unique field i.e id (but with different values)
I need to pass on value of id and v_prod_id in a url
say url been :-
<a href="index.php?option=com_usedcar&pid='.$row->v_prod_id.'&vid='.$row->id.'">
But id been common field in most of the tables hence its not picking in correctly from nfojm_usedcar_variants,
Can some one help to modify a function so as to fetch in value of id and v_prod_id from the respective table of nfojm_usedcar_variants
thanks
If you have multiple tables in a join that share a common column name, and you need them, then alias them. Such as:
select a.id as aid,a.theName,b.id as bid,b.year
from tableA a
join tableB b
on b.id=a.id
then refer to those columns as aid and bid in your code that follows.
Try to avoid Ever doing a select *. Be explicit. You never know what comes flying out of a select * typically. And odds are you don't need it all. Select * is fine for messing around, but not for production code. And you can't control common column names with select *. We like to control things afterall, no?
I have a table called faq. This table consists from fields faq_id,faq_subject.
I have another table called article which consists of article_id,ticket_id,a_body and which stores articles in a specific ticket. Naturally there is also a table "ticket" with fields ticket_id,ticket_number.
I want to retrieve a result table in format:
ticket_number,faq_id,faq_subject.
In order to do this I need to search for faq_id in the article.a_body field using %LIKE% statement.
My question is, how can I do this dynamically such that I return with SQL one result table, which is in format ticket_number,faq_id,faq_subject.
I tried multiple configurations of UNION ALL, LEFT JOIN, LEFT OUTER JOIN statements, but they all return either too many rows, or have different problems.
Is this even possible with MySQL, and is it possible to write an SQL statement which includes #variables and can take care of this?
First off, that kind of a design is problematic. You have certain data embedded within another column, which is going to cause logic as well as performance problems (since you can't index the a_body in such a way that it will help the JOIN). If this is a one-time thing then that's one issue, but otherwise you're going to have problems with this design.
Second, consider this example: You're searching for faq_id #123. You have an article that includes faq_id 4123. You're going to end up with a false match there. You can embed the faq_id values in the text with some sort of mark-up (for example, [faq_id:123]), but at that point you might as well be saving them off in another table as well.
The following query should work (I think that MySQL supports CAST, if not then you might need to adjust that).
SELECT
T.ticket_number,
F.faq_id,
F.faq_subject
FROM
Articles A
INNER JOIN FAQs F ON
A.a_body LIKE CONCAT('%', F.faq_id, '%')
INNER JOIN Tickets T ON
T.ticket_id = A.ticket_id
EDIT: Corrected to use CONCAT
SELECT DISTINCT t.ticket_number, f.faq_id, f.faq_subject
FROM faq.f
INNER JOIN article a ON (a.a_body RLIKE CONCAT('faq_id: ',faq_id))
INNER JOIN ticket t ON (t.ticket_id = a.ticket_id)
WHERE somecriteria