How to join multiple columns from the same table? - mysql

I have a table called FieldList that looks like this:
ElementName|Description|comp_id|FieldName
-----------------------------------------
Name | red | 1 | names
Name | blue | 7 | names
field | red | 1 | names
boxes | blue | 5 | blues
field | orange | 7 | reds
And I want to show a new table that shows only the ElementNames that are the same and then show which comp_id they belong to so it looks like this:
ElementName| comp_id| comp_id
-----------------------------
Name | 1 | 7
field | 1 | 7
It doesnt have to look exactly like this but the point is I want to be able to join and show the ElementNames that are identical but have different comp_id's.
This is the little bit of sql code that I have already but its obviously not working.
SELECT a.comp_id, a.ElementName, b.ElementName
FROM FieldList a
INNER JOIN FieldList b ON a.ElementName = b.ElementName;

You seem to want element names that have the same comp ids. If so, you can use group_concat() like this:
select group_concat(elementname), comps
from (select fl.elementname, group_concat(fl.comp_id order by fl.comp_id) as comps
from fieldlist fl
group by fl.elementname
) en
group by comps;
This actually produces rows with two lists:
Name,field 1,7
But it seems to contain the information you want.

This query may accomplish what you want:
SELECT a.ElementName, a.comp_id, b.comp_id
FROM FieldList a
JOIN FieldList b ON a.ElementName = b.ElementName
WHERE a.comp_id != b.comp_id
GROUP BY a.ElementName, (a.comp_id + b.comp_id);
Note that I am grouping by the addition of the two comp_ids. If I didn't, you wouldn't get rows for each duplication.

Try this...
SELECT a.ElementName, a.comp_id, b.comp_id
From FieldList a
left join FieldList b on
a.ElementName = b.ElementName and
a.comp_id <> b.comp_id
WHERE a.comp_id is not null

Related

Select rows where join table has same value

product_options
ID | Option
1 | One
2 | Two
3 | Three
product_to_options
ID | Product | Option
1 | 1 | 1
2 | 2 | 2
3 | 2 | 3
Essentially, I need to get all the rows from product_options, apart from the
ones that are supplied where the options are on the same products.
For example:
Passing the value of 1, would return nothing.
Passing the value of 2, would return the option with ID 3
Passing the value of 3, would return the option with ID 2.
I did my best with what I understand.
pto.Product = #option so you get all the rows match #option
pto.Option <> #option but filter those with the same ID
.
SELECT po.*
FROM product_options po
JOIN (
SELECT pto.Option
FROM product_to_options pto
WHERE pto.Product = #option
AND pto.Option <> #option
) as filter
ON PO.ID = filter.Option
You can join a table to itself, filter the left table on the value and return the value from the right table.
SELECT
pto2.Option
FROM
product_to_options pto1
INNER JOIN product_to_options pto2
ON pto1.Product = pto2.Product
AND pto1.ID <> pto2.ID
WHERE
pto1.option = #option;
You should note that you can get more than one value back depending on the data.
Here's a working sample with minor syntax changes for sql server (you'll need to check text-only-results or click through the grid)

Issue with mysql query that calls column name from another table

I have two tables, one is an index (or map) which helps when other when pulling queries.
SELECT v.*
FROM smv_ v
WHERE (SELECT p.network
FROM providers p
WHERE p.provider_id = v.provider_id) = 'RUU='
AND (SELECT p.va
FROM providers p
WHERE p.provider_id = v.provider_id) = 'MjU='
LIMIT 1;
Because we do not know the name of the column that holds the main data, we need to look it up, using the provider_id which is in both tables, and then query.
I am not getting any errors, but also no data back. I have spent the past hour trying to put this on sqlfiddle, but it kept crashing, so I just wanted to check if my code is really wrong, hence the crashing?
In the above example, I am looking in the providers table for column network, where the provider_id matches, and then use that as the column on smv.
I am sure i have done this before just like this, but after the weekend trying I thought i would ask on here.
Thanks in Advance.
UPDATE
Here is an example of the data:
THis is the providers, this links so no matter what the name of the column on the smv table, we can link them.
+---+---+---------------+---------+-------+--------+-----+-------+--------+
| | A | B | C | D | E | F | G | H |
+---+---+---------------+---------+-------+--------+-----+-------+--------+
| 1 | 1 | Home | network | batch | bs | bp | va | bex |
| 2 | 2 | Recharge | code | id | serial | pin | value | expire |
+---+---+---------------+---------+-------+--------+-----+-------+--------+
In the example above, G will mean in the smv column for recharge we be value. So that is what we would look for in our WHERE clause.
Here is the smv table:
+---+---+-----------+-----------+---+----+---------------------+-----+--+
| | A | B | C | D | E | F | value | va |
+---+---+-----------+-----------+---+----+---------------------+-----+--+
| 1 | 1 | X2 | Home | 4 | 10 | 2016-09-26 15:20:58 | | 7 |
| 2 | 2 | X2 | Recharge | 4 | 11 | 2016-09-26 15:20:58 | 9 | |
+---+---+-----------+-----------+---+----+---------------------+-----+--+
value in the same example as above would be 9, or 'RUU=' decoded.
So we do not know the name of the rows, until the row from smv is called, once we have this, we can look up what column name we need to get the correct information.
Hope this helps.
MORE INFO
At the point of triggering, we do not know what the row consists of the right data because some many of the fields would be empty. The map is there to help we query the right column, to get the right row (smv grows over time depending on whats uploaded.)
1) SELECT p.va FROM providers p WHERE p.network = 'Recharge' ;
2) SELECT s.* FROM smv s, providers p WHERE p.network = 'Recharge';
1) gives me the correct column I need to look up and query smv, using the above examples it would come back with "value". So I need to now look up, within the smv table, C = Recharge, and value = '9'. This should bring me back row 2 of the smv table.
So individually both 1 and 2 queries work, but I need them put together so the query is done on the database server.
Hope this gives more insight
Even More Info
From reading other posts, which are not really doing what I need, i have come up with this:
SELECT s.*
FROM (SELECT
(SELECT p.va
FROM dh_smv_providers p
WHERE p.provider_name = 'vodaphone'
LIMIT 1) AS net,
(SELECT p.bex
FROM dh_smv_providers p
WHERE p.provider_name = 'vodaphone'
LIMIT 1) AS bex
FROM dh_smv_providers) AS val, dh_smv_ s
WHERE s.provider_id = 'vodaphone' AND net = '20'
ORDER BY from_base64(val.bex) DESC;
The above comes back blank, but if i replace net, in the WHERE clause with a column I know exists, I do get the results expected:
SELECT s.*
FROM (SELECT
(SELECT p.va
FROM dh_smv_providers p
WHERE p.provider_name = 'vodaphone'
LIMIT 1) AS net,
(SELECT p.bex
FROM dh_smv_providers p
WHERE p.provider_name = 'vodaphone'
LIMIT 1) AS bex
FROM dh_smv_providers) AS val, dh_smv_ s
WHERE s.provider_id = 'vodaphone' AND value = '20'
ORDER BY from_base64(val.bex) DESC;
So what I am doing wrong, which is net, not showing the value derived from the subquery "value" ?
Thanks
SELECT
v.*,
p.network, p.va
FROM
smv_ v
INNER JOIN
providers p ON p.provider_id = v.provider_id
WHERE
p.network = 'RUU=' AND p.va = 'MjU='
LIMIT 1;
The tables talk to each other via the JOIN syntax. This completely circumvents the need (and limitations) of sub-selects.
The INNER JOIN means that only fully successful matches are returned, you may need to adjust this type of join for your situation but the SQL will return a row of all v columns where p.va = MjU and p.network = RUU and p.provider_id = v.provider_id.
What I was trying to explain in comments is that subqueries do not have any knowledge of their outer query:
SELECT *
FROM a
WHERE (SELECT * FROM b WHERE a)
AND (SELECT * FROM c WHERE a OR b)
This layout (as you have in your question) is that b knows nothing about a because the b query is executed first, then the c query, then finally the a query. So your original query is looking for WHERE p.provider_id = v.provider_id but v has not yet been defined so the result is false.

How can I get connected values of two times the same foreign key?

I currently have a situation that could easily be solved with 3 SQL queries, but I wonder if it can be done in one query.
I have the following tables:
symbol similarity
------- ------------
id | name | latex id | base_symbol_id | similar_symbol_id
I want to SELECT so that my result looks like this:
query_result
------------
similarity_id | base_formula_id | base_formula_name | base_formula_latex | similar_formula_id | similar_formula_name | similar_formula_latex
Failed tries
I usual solve similar tasks with JOIN. But this time, the SELECT depends on another attribute I select ... I don't know how to do this. Here is my try (which of course failed):
SELECT `base_symbol_id`, `similar_symbol_id`, `latex`
FROM `similarity`
JOIN `symbol` ON ((`symbol`.`id` = `base_symbol_id`) OR (`symbol`.`id` = `similar_symbol_id`))
gives
base_symbol_id | simlar_symbol_id | latex
10 | 11 | \alpha
10 | 11 | a
select sim.id
,base.id
,base.name
,base.latex
,similar.id
,similar.name
,similar.latex
from similarity as sim
join symbol as base on base.id=sim.base_symbol_id
join symbol as similar on similar.id=sim.similar_symbol_id
Using the given table structure, and making up some random sample inputs in an SQL Fiddle session, the following query would work as you desired:
SELECT T.id as similarity_id,
S1.id as base_formula_id, S1.name as base_formula_name, S1.latex as base_formula_latex,
S2.id as similar_formula_id, S2.name as similar_formula_name, S2.latex as similar_formula_latex
FROM similarity T
LEFT OUTER JOIN symbol S1 ON (T.base_symbol_id = S1.id)
LEFT OUTER JOIN symbol S2 ON (T.similar_symbol_id = S2.id)

MySql Impass - can't move forward

I currently have this sql statement that I wrote and it works but it's not quite what I want. I've been working on it for hours but can't seem to get any further.
select parent.id as parent_id, parent.subject as parent,s.id,s.subject from (select s.id, s.subject from subjects s where parent_id = 0) parent join subjects s on parent.id = s.parent_id order by parent.subject, s.subject
It's grabbing all the subjects and ordering correctly but I also want to return the parent subject (parent_id = 0) at the top of each grouping. This is because some parents may not have subjects underneath but I still need to return them. Also the ordering is off when I try to do it as I want the parent first then it's child subjects. Hope that makes sense but if not just ask.
Any help would be appreciated.
Thanks
Steve
You're talking about grouping sets of rows by their parent rows.
The only way I know how to do this in MySQL is using the GROUP_CONCAT() function which won't group the subjects by row, but rather create a grouped string.
Here's what you can do:
SELECT
a.id,
a.subject,
GROUP_CONCAT(CONCAT(b.id, ':::', b.subject) ORDER BY b.subject SEPARATOR '|||') AS subjectlist
FROM
subjects a
LEFT JOIN
subjects b ON a.id = b.parent_id
WHERE
a.parent_id = 0
GROUP BY
a.id,
a.subject
ORDER BY
a.subject
So this will give you a result set like:
id | subject | subjectlist
---------------------------------------------------------------------
2 | subj1 | 23:::childsubj1|||28:::childsubj4
3 | subj2 | 18:::childsubj8|||55:::childsubj16
4 | subj3 | NULL
Depending on what language you are using in your application, you may be able to "explode" the subjects string into arrays delimited first by ||| which separates each subject, then ::: which separates that subject's ID and name.
Obviously, the downside of this is you have to make sure that your child subject name does not contain either ||| or ::: or whichever delimiters you decide to use.
Edit: Experimentally, I came up with this alternative solution which may be closer to what you're looking for:
Try:
SELECT
c.subj,
c.id
FROM
(
SELECT
CONCAT('---> ', b.subject) AS subj,
b.id,
CONCAT(a.subject, b.subject) AS orderfactor
FROM
subjects a
INNER JOIN
subjects b ON a.id = b.parent_id
WHERE
a.parent_id = 0
UNION ALL
SELECT
subject AS subj,
id,
subject AS orderfactor
FROM
subjects
WHERE
parent_id = 0
) c
ORDER BY
c.orderfactor
This query should give you a result along the lines of:
subject | id |
----------------------------------------------------------
subj1 | 2 |
---> childsubj1 | 23 |
---> childsubj4 | 28 |
subj2 | 3 |
---> childsubj8 | 18 |
---> childsubj16 | 55 |
subj3 | 4 |
subj4 | 5 |
---> childsubj10 | 79 |

Complex Mysql string not returning row

i have 3 rows on "Services" table:
ID | name | ObrID
0 | A | 1
1 | B | 2
2 | C | -1
-1 is a none existing Obr, the service 2 doesn't contains any Obr or it was deleted.
if i fetch with select * from Services, it works as expected, but if i do my search sql:
select
*,
(select Name from Obrs where ID=ObrID) as ObrName
from
Services
where
(select Name from Obrs where ID=ObrID) like '%SEARCH_STRING%'
it doesn't return the last line. Is there any way so it return something like:
ID | name | ObrID | ObrName
0 | A | 1 | ObrA
1 | B | 2 | ObrB
3 | C | -1 | NULL
You want to use left join.
http://www.tizag.com/mysqlTutorial/mysqlleftjoin.php
SELECT s.*,o.ObrName from Services s
LEFT JOIN Obrs o ON ID=ObrID
WHERE OrbName LIKE '%$SEARCH_STRING%' OR OrbName IS NULL
or:
SELECT * FROM (select s.*,o.ObrName from Services s
LEFT JOIN Obrs o ON ID=ObrID) tmp
WHERE OrbName LIKE '%$SEARCH_STRING%' OR OrbName IS NULL
May be below can help:
select s.*,ob.Name from Services as s left join Obrs as ob on s.ID=ob.ObrID where ob.Name like '%$SEARCH_STRING%';
If there is no Obrs.Name because your ObrID is -1, then Obrs.Name will be NULL and therefor not LIKE '%$SEARCH_STRING%'. You can add an additional condition to also include these cases:
where
(select Name from Obrs where ID=ObrID) like '%$SEARCH_STRING%'
OR ObrID = -1
And follow Flöcsy's suggestion and use a LEFT JOIN. Joins are always the preferred method, especially vs. correlated subquerys. The working condition when using a LEFT JOIN is
WHERE
Obrs.Name LIKE '%$SEARCH_STRING%'
OR Obrs.Name IS NULL