Suppose that we have, in mysql, a table "mytable"
with the columns: id, title, type.
Is it possible to use its column as a table name in the same query?
For example:
SELECT m.id, m.title FROM mytable m INNER JOIN m.type WHERE m.id=2
Where "type" will give me the name of the table to do the inner join.
No, Sorry :(
The closest you can get (afaik) is to cursor through your main table and write dynamic html for the join for each row. VERY slow.
Or, find a new design pattern - Is there scope for you to post a question about what you are trying to achieve and how people may go about that?
Why not put all of your type data in a single table ? and then partition the table by type.
Related
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
I have three tables :
bldr_prjct,bldr_prjct_attr,bldr_prjct_attr_ref;
i want to get bldr_prjct data where bldr_prjct attributes are stored in bldr_prjct_attr.
bldr_prjct_attr_ref : In this table i have defined values all attributes related to projects :
Screenshots :
bldr_prjct
bldr_prjct_attr_ref :
bldr_prjct_attr :
My query :
SELECT
`p`.`ID`,`p`.`PRJCT_NM`,`p`.`SLUG`,`p`.`STS_CD`,
`p`.`PRJCT_GEO_LT`,`p`.`PRJCT_GEO_LG`
FROM
`bldr_prjct` `p`, `bldr_prjct_attr_ref` `pr`, `bldr_prjct_attr` `pa`
WHERE
`pa`.`REF_ID` IN (SELECT `ID` FROM `bldr_prjct_attr_ref` WHERE `PRNT_ID`=3)
Firstly, don't use implicit JOIN syntax(comma separated) , use the proper syntax of join, that will help you avoid this kind of mistakes.
You query is not working because you are missing the join relations , you may have to adjust it a bit, i guessed bldr_prjct is joined to bldr_prjct_attr_ref by id=prnt_id although you have prnt_id column in this table, so change it if needed.
SELECT `p`.`ID`,`p`.`PRJCT_NM`,`p`.`SLUG`,`p`.`STS_CD`,`p`.`PRJCT_GEO_LT`,`p`.`PRJCT_GEO_LG`
FROM `bldr_prjct` `p`
INNER JOIN `bldr_prjct_attr` `pa`
ON(`p`.id = `pa`.prnt_id )
INNER JOIN `bldr_prjct_attr_ref` `pr`
ON(`pa`.ref_id = `pr`.id and `pr`.prnt_id = 3 )
I might be missing something, but your tables don't appear to have any common reference. For instance, table bldr_prjct_attr_ref does not include any field pointing to the relevant record in table bldr_prjct. If my understanding is correct, you will have to alter these tables to allow some time of cross-referencing. For instance, add to table bldr_prjct_attr_ref a field (column) bldr_prjct_ID that points to the corresponding record in table bldr_prjct.
There is one field in the third table that appears to reference a record in the first, but when you issue a SELECT of three tables and one of them returns an empty result, then the overall select returns empty.
I need to join 3 tables which have some columns with same name, like id and some foreign keys columns.
I make a select query and the results come with table names only. How to get results like "dbname"."columnname" in my queries so I can identify from which table is each columns without having to specify every columns in the query (using only an *)?
Note: I use Delphi with ZeosLib, so a solution using these tools would be OK as well. But I prefer to set this in the data base.
You have to create an alias for your field name in your query
SELECT a.ID, b.ID
FROM a
JOIN b
You need doblue quote " for field names with special characters, so change it to.
SELECT a.ID "a.ID", b.ID "b.ID"
OR
SELECT a.ID "MeaningfullName", b.ID "OtherName"
For example here I have two fields name "sent_dt" and change one to previous_time
SQL Fiddle Demo
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.
I know how to update one table's field from another table's count using t1.id=t2.id etc.. but i have somewhat typical issue. I have to use LIKE STATEMENT in WHERE clause.
This is something similar i wanted to do.
UPDATE `CATEGORIES`
SET `num_listings` = (SELECT COUNT(*)
FROM `LISTINGS`
WHERE `LISTINGS`.`CATEGORY` LIKE
ws_concat('', "%-", `CATEGORIES`.`ID`, "-%"));
(Example: I have CATEGORY stored as -25- in the LISTINGS table as a field name CATEGORY)
I understand that i cannot use ws_contact here but is there another way to achieve it?
Thanks in advance.
Unless there is a good reason for the category ID to be represented only by a part of a string in the listings table, the best way to handle such a structure of data is to add a category_id column to the LISTINGS table, and make sure that when adding or editing a listing this column is populated properly.
This would allow to simply JOIN the two tables ON categories.id = listings.category_id and makes much more sense. This would also give better performance by far.
If you do want to keep the DB structure as is, you can use a temporary table, with LIKE and CONCAT:
DROP TABLE IF EXISTS temp;
CREATE TABLE temp AS
SELECT categories.id, COUNT(*) AS c
FROM categories
JOIN listings ON listings.category LIKE CONCAT('%',categories.id,'%')
GROUP BY categories.id;
UPDATE categories, temp
SET categories.num_listings = temp.c
WHERE categories.id = temp.id;