Last time you guys were super helpful, let's hope we can also resolve the following challenge that I'm having.
I have 2 tables in the same database and trying to match fields. Here is the query I'm looking for with the table name however I cannot get it to work:
I want to MATCH table "projects" and Column "categorysecond" table "users_profile" and Column "category".
projects.categorysecond might include example; "Roofing,Windows,Landscaping" and users_profile.category might only have EITHER "Roofing" OR "Windows" OR "Landscaping", so I want to pull the results from "projects" if a result from users_profile.category FITS in projects.categorysecond
***Important - I do not have unique identifiers to do a inner join on example ID. The only match should be on the tables listed above, if words(%Wildcard) from one fits the other.
SAMPLE OF MY ATTEMPT
$sql = "SELECT DISTINCT users_profiles.username, projects.id FROM users_profiles, projects WHERE users_profiles.category like '%' + projects.categorysecond + '%'";
Does this make sense? :)
Thank you in advance.
select distinct
up.username
,p.id
from users_profiles as up
join projects as p
on concat(',',p.categorysecond,',') like concat('%,',up.category,',%')
You have a really bad data format. You should not be storing lists of things in a comma-delimited field. The trouble you are having with this query is just one example of the issues. You cannot get such queries to take advantage of indexes or other optimization techniques.
Sometimes, we are stuck with other people's really bad design decisions. MySQL has the function find_in_set() with works in this case:
SELECT DISTINCT up.username, p.id
FROM users_profiles up JOIN
projects p
ON find_in_set(up.category, p.categorysecond) > 0;
Note: If you don't need the DISTINCT, then don't include it. It just incurs a performance penalty.
Related
I'm currently working on a project that requires me look at someone elses code, i'm still new to some of this stuff and there is something that I dont quite understand so was hoping someone could shed some light on what the code is actually doing or what it means?
Here is the statement in question:
select s.* from $tableA n, $tableB s where
n.id='$send' and
n.status='$status' and
n.field=s.id";
I understand that down to basics this statement is getting all of the fields from tableA and tableB im just unsure what the s. does or what the n does in this statement? are they simply there as identifiers or am I completely wrong in this manner? I am happy to provide more information if it is necessary.
They are called SQL Table Aliases and are basically temporary names which you give to the tables in order to have better readability when you use the table names to specify a column.
In your example
SELECT s.* FROM $tableA n, $tableB s
WHERE n.id='$send'
AND n.status='$status'
AND n.field=s.id ;
is the same as
SELECT $tableB.* FROM $tableA, $tableB
WHERE $tableA.id='$send'
AND $tableA.status = '$status'
AND $tableA.field = $tableB.id ;
but obviously it's easier to read.
The table aliases are even more useful when you join more tables and are absolutely a must when you make self joins.
Syntax note:
You may or you may not use the AS keyword when alias a table.
SELECT table_name AS alias
is the same as
SELECT table_name alias
and although it's longer sometimes it leads to a better readability (for example in a large and messy query the big AS is easier to spot :)
This question is not to discuss if the setup of the DB is as it should be, i'm not happy with how it is, but it is how it is and a refactor will not be done by the DBA at this moment.
What i am looking for is a way to join a table, for which i do not in advance know the table name but it is in the table i want to do the join against.
So:
TABEL transactions
trans_id autherizer
001Bar payment_provider_a
001Foo payment_provider_b
TABLE payment_provider_a
trans_id amount
001Bar 50
TABLE payment_provider_b
trans_id amount
001Foo 50
The table names are fictional, but the setup is identical. There is a transaction table, which stores an transaction_id and a payment_provider string name (with a lot of additional data, which is not relevant for the question).
Would there be anyway to get all the data from the transaction table and in that query do directly a join on the payment_provider table, for which we only now what that table can be from the transaction table.
I have tagged it with PHP as well, since i want to make the call with PDO. Whole PHP snippets are not required, but if you insist ;). A push in the right direction for the query it self would be sufficient. I am aware that i am lacking the example of what i have tried. But to be honest i haven't tried that much because i can't really think of something, it's the first time i am in this kind of need for such a query.
Not overly clean, but you can try this:
SELECT * FROM transactions t JOIN
(
SELECT 'payment_provider_a' AS name,* FROM payment_provider_a
UNION
SELECT 'payment_provider_b' AS name,* FROM payment_provider_b
) p ON t.payment_provider = p.name AND t.trans_id=p.trans_id
Note that all payment_provider_x tables must have the same number and types of columns. Otherwise you'll need to select only the fields that are actually common (there are ways around this if needed).
I had my query set up the other day as so
$query = "SELECT card_id,title,description,meta_description,seo_keywords,price
FROM cards,card_cheapest order by card_id";
As you can see, I was selecting card_id,title,description,meta_description,seo_keywords from the table cards, and price was coming from cheapest_card. They both have the card_id in common (in both tables). However, I ran into a bit of an issue. When I run the query in navicat lite, I receive an error "card_id is ambiguous". Was I doing something wrong?
When 2 or more tables have a column that is named the same, you have to qualify the table you want the column to be from.
i.e.:
$query = "SELECT cards.card_id,title,description,meta_description,seo_keywords,price
FROM cards,card_cheapest order by card_id";
Furthermore, do you really want to run the query this way, without a WHERE/JOIN-clause to define how to JOIN the two tables?
$query = "SELECT cards.card_id,title,description,meta_description,seo_keywords,price
FROM cards,card_cheapest WHERE cards.card_id = card_cheapest.card_id
ORDER BY card_id";
When you have the same column name in two tables you're selecting from, you have to prefix the part in the SELECT with one of the table names (it doesn't matter which if it's the same data)
such as SELECT cards.card_id, ...
EDIT: However, cularis's answer is much more explanatory than mine, and take note about joining the two card_id columns if you want to get correct results.
When you run queries that get information from multiple tables with shared field names you need to specify from which table you want to extract what field. You do this by specifying the table name before the field name.
In your case you have two options:
cards.card_id or card_cheapest.card_id.
Also I agree with #cularis, you are probably better of doing a join, but still you will need to specify which card_id you want to select: the one from cards or card_cheapest.
I have a programme listing database with all the information needed for one programme packed into one table (I should have split programmes and episodes into their own) Now since there are multiple episodes for any given show I wish to display the main page with just the title names in ascending and chosen letter. Now I know how to do the basic query but this is all i know
SELECT DISTINCT title FROM programme_table WHERE title LIKE '$letter%'
I know that works i use it. But I am using a dynamic image loading that requires a series number to return that image full so how do I get the title to be distinct but also load the series number from that title?
I hope I have been clear.
Thanks for any help
Paul
You can substitute the DISTINCT keyword for a GROUP BY clause.
SELECT
title
, series_number
FROM
programme_table
WHERE title LIKE '$letter%'
GROUP BY
title
, series_number
There are currently two other valid options:
The option suggested by Mohammad is to use a HAVING clause in stead of the WHERE clause this is actually less optimal:
The WHERE clause is used to restrict records, and is also used by the query optimizer to determine which indexes and tables to use. HAVING is a "filter" on the final result set, and is applied after ORDER BY and GROUP BY, so MySQL cannot use it to optimize the query.
So HAVING is a lot less optimal and you should only use it when you cannot use 'WHERE' to get your results.
quosoo points out that the DISTINCT keyword is valid for all listed columns in the query. This is true, but generally people do not recommend it (there is no performance difference *In some specific cases there is a performance difference***)**. The MySQL optimizer however spits out the same query for both so there is no actual performance difference.
Update
Although MySQL does apply the same optimization to both queries, there is actually a difference: when DISTINCT is used in combination with a LIMIT clause, MySQL stops as soon as it finds enough unique rows. so
SELECT DISTINCT
title
, series_number
FROM
programme_table
WHERE
title LIKE '$letter%'
is actually the best option.
select title,series_number from programme_table group by title,series_number having title like '$letter%';
DISTINCT keyword works actually for a list of colums so if you just add the series to your query it should return a set of unique title, series combinations:
SELECT DISTINCT title, series FROM programme_table WHERE title LIKE '$letter%'
Hey thanks for that but i have about 1000 entries with the same series so it would single out the series as well rendering about 999 programmes useless and donot show.
I however found out away to make it unique and show the series number
SELECT * FROM four a INNER JOIN (SELECT title, MIN(series) AS MinPid FROM four WHERE title LIKE '$letter%' GROUP BY title) b ON a.title = b.title AND a.series = b.MinPid
Hopefully it helps anyone in the future and thank you for the replies :)
I want to make a search engine in an intranet. Now i use this clause in PHP.
$k = explode(" ",$_GET[key]);
$sql = "select entreprise.*, employee.* where entreprise.* or employee.* like '%$k[0]%' or '%$k[1]%'";
But it seems doesn't work. Do you know where is wrong?
Thanks in advance.
Edit:
$sql = "select * from entreprise, site, salarie where entreprise.*, site.*, salarie.* like '%$k[0]%' or '%$k[1]%'";
I have modified the query clause. With this code, i think you can know what i want to do.
I want to find anything that matches the content in all the columns of entreprise table and the content in all the columns of employee table.
It's hard to exactly see what you're trying to do, but you need, in your SQL query, to specify :
on which tables you are working, with a from clause
on which fields the search has to be done, in the where clause.
how the data between employees and enterprises are related :
do you want to search for entreprises and their employees ?
for employees and there enterprises ?
for all enterprises and the employees when the employee or the enterprise contains the words ?
You could use something like this to search for entreprises that contain the word, and get their employees to :
select *
from entreprise
inner join employee on employee.id_entreprise = entreprise.id
where entreprise.name like '%word%'
or entreprise.description like '%word%';
Or, to search for employees that match the criteria and get their entreprise too :
select *
from employee
inner join entreprise on entreprise.id = employee.id_entreprise
where employee.name like '%word%';
(just some ideas -- you'll have to build from there !)
This:
$sql = "select entreprise.*, employee.* where entreprise.* or employee.* like '%$k[0]%' or '%$k[1]%'";
is not valid SQL. It is hard to guess what you want to do, but I'm trying anyway: you want to find employees, and search them by name or by enterprise that employs them. Is that the case? Or do you want to search employess and/or enterprises?
EDIT
I want to find anything that matches the content in all the columns of entreprise table and the content in all the columns of employee table.
Ok, first of all you should realize that SQL is probably not the best tool for this job. See the other commenter - his suggestions about sphinx and friends are good. But still, if you really want to:
$sql = '
SELECT e.id, e.name
FROM enterprise e
-- first, look in column1
WHERE e.column1 LIKE '."'%".$k[0]."%'".'
OR e.column1 LIKE '."'%".$k[1]."%'".'
...etc for all entries in k...
OR e.column1 LIKE '."'%".$k[N]."%'".'
-- then, look in column2
OR e.column2 LIKE '."'%".$k[0]."%'".'
OR e.column2 LIKE '."'%".$k[1]."%'".'
...and so on and so forth for all entries in $k and all columns in enterprise...
UNION ALL
SELECT s.id, s.name
FROM salarie s
WHERE ...and the same for columns of salarie...
...
UNION ALL
...any other tables you want to search...
';
As you can see, not something that makes you happy.
Another approach that might give you more joy is having some overnight job to scan all rows in the tables you're interested in, parse the texts you want to search into separate words, and store those in a keyword table, and storing the association between an object from the source database and the keyword in a separate table. You can then search the keyword table and use the id's and table names you find for a collection of keywords to build the actual query to retrieve those rows. This is what I do, and it works great. It works better because there is a relatively small amount of words that you will encounter, whereas the collection of objects is quite possible very large.