These are my tables:
language language_person person
+----+----------+ +----+-----------+-----------+ +----+-----------------+
| id | name | | id | languageId| personId | | id | name |
+----+----------+ +----+-----------+-----------+ +----+-----------------+
| 1 | english | | 1 | 1 | 1 | | 1 | luca |
+----+----------+ +----+-----------+-----------+ +----+-----------------+
| 2 | german | | 2 | 2 | 1 | | 2 | sara |
+----+----------+ +----+-----------+-----------+ +----+-----------------+
| 3 | italian | | 3 | 3 | 1 | | 3 | michael |
+----+----------+ +----+-----------+-----------+ +----+-----------------+
| 4 | 3 | 2 |
+----+-----------+-----------+
| 5 | 2 | 3 |
+----+-----------+-----------+
Currently I'm loading with JPA a person and a list of the languages spoken by this person.
Every person talks at least one language. Now I would like to implement a query, to get all the person that talks exactly and only the same languages. In case of 'Luca', I search someone that talks english AND german AND italian. When searching with a query like WHERE languageId IN (1, 2, 3) I obviously get all person back that talk at least one of the languages. Also when searching for someone like 'sara', I search for someone talking ONLY italian, no other language.
It's completely out of my understanding, so any help is higly appreciated.
I think the simplest way is to use aggregation and window functions:
select id, name
from (select p.id, p.name,
group_concat(lp.languageid order by lp.languageid) as languageids,
max(case when p.name = 'Luca' then group_concat(lp.languageid order by lp.languageid) end) over () as luca_languageids
from language_person lp join
person p
on lp.personid = p.id
group by p.id, p.name
) p
where languageids = luca_languageids;
Related
I have a bunch of articles
+-----------+-------+
| ArticleID | Name |
+-----------+-------+
| 1 | Bla |
| 2 | Blub |
| 3 | Test |
+-----------+-------+
And Prodcutgroups:
+-----------+--------------+
| ProductGroupID | Name |
+-----------+--------------+
| 4 | Group A |
| 5 | Group B |
| 6 | Group C |
+-----------+--------------+
And a link table (M:N relation) that links articles with product-groups. Each article can be in many product-groups at the same time but only once per group:
+-----------+----------------+
| ArticleID | ProductGroupID |
+-----------+----------------+
| 1 | 4 |
| 1 | 5 |
| 2 | 5 |
| 2 | 6 |
| 3 | 4 |
| 3 | 6 |
+-----------+----------------+
My problem is now that I need a query that lets me find out articles that are MISSING in product-group with ID 4.
Usually I would write a PHP Script that loops entire table and checks for values and remembers if product-group-id 4 was not found.
But this seems very sophisticated and annoying as I have this kind of szenario more often here and there.
I cannot use WHERE ProductGroupID NOT IN(4) because when the article is assigned to OTHER product-groups it will find that rows and
the result will NOT tell me wether the article is in this specific group or not.
The result would need to give me only!! Article-ID: 2 as its not in Product-Group with ID 4
I appreciate any helpful advice!
One option, using exists logic:
SELECT a.Name
FROM articles a
WHERE NOT EXISTS (SELECT 1 FROM link l
WHERE l.ArticleID = a.ArticleID AND l.ProductGroupID = 4);
Read in plain English, the above query says to return the name of article for which we cannot find an entry in the link table associated with ProductGroupID = 4.
I have working on database for dictionary project. I have to store a word and meaning with -- many to many -- relationship.
Below I have mentioned the sample with my table structure. I hope the table structure is right, but I don't know how to select all meanings for single word while user searching.
And also I have to write a query to select all word linked to a single meaning.
And also I have to write a query to select all meaning linked to a single word.
word_table
+----+------+
| id | word |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
+----+------+
meaning_table
+----+--------+
| id | meaning|
+----+--------+
| 1 | X |
| 2 | Y |
| 3 | Z |
+----+--------+
word_meaning_table
+---------+-----------+
| word_id | meaning_id|
+---------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
| 3 | 2 |
| 3 | 3 |
+---------+-----------+
Expected output should be like this.
If user searching for a word "A" in word table the result should be
Result for word "A"
+----+----------+
| word| meaning |
+----+----------+
| A | X |
| A | Y |
| A | Z |
+----+----------+
I don't know how to write a join query for this scenario.
SELECT wt.word, mt.meaning
FROM word_table wt
INNER JOIN word_meaning_table wmt
ON wt.id = wmt.word_id
INNER JOIN meaning_table mt
ON wmt.meaning_id = mt.id
WHERE wt.word = 'A'
Follow the link below for a working demo:
SQLFiddle
Try
select word, meaning
from word_table
join meaning_table on word_table.id=meaning_table.id;
I use MySQL,
In my database, I have this table :
+-----------------------------+
| ID NAME ID_FATHER |
+-----------------------------+
| 1 Mylodi 0 |
| 2 Jack 0 |
| 3 Linda 1 |
| 4 Mark 2 |
| 5 Simon 4 |
| 6 Sacha 1 |
| 7 Edward 1 |
+-----------------------------+
By this query I retrieve each name with his father :
select f.name as father, s.name as son from family s, family f where s.id_father = f.id
Result
+------------+---------+
| father | son |
+------------+---------+
| mylodi | linda |
| Jack | mark |
| mark | simon |
| mylodi | sacha |
| mylodi | edward |
+------------+---------+
But, my question How can I get this result, but in one column like this :
+--------+
| colum |
+--------+
| Mylodi |
| linda |
| sacha |
| edward |
| jack |
| mark |
| simon |
+--------+
that mean I want to display the name of the Father and of below each name of father names of his son. Thanks.
EDIT
this is my db structure
How about something like this:
SELECT name FROM (
SELECT id, name, id sort1, id_father sort2 FROM family WHERE id_father = 0
UNION
SELECT id, name, id_father, 1 sort2 FROM family WHERE id_father <> 0
) AS v
ORDER BY sort1, sort2
Here's an updated fiddle.
This is not so straightforward. It assumes that there are no loops in the data (a is b's father and b is a's father)
Not sure what database you are using, but Oracle has Hierarchical queries that are meant for problems like this using the "connect by" keyword.
I am trying to get a result from two tables without having a second query nested inside the first query loop.
I have a table products:
product_code_1234 | product_name | otherfields...
And a table categories, where a product can have multiple categories:
category_name_1 | product_code_1234
category_name_2 | product_code_1234
category_name_3 | product_code_1234
Is there a query to get the following result?
product_code_1234 | product_name | ... | category_name_1 | category_name_2 | category_name_3
select * from a,b
will give you all data from table a ,combined with all data from table b.
However if you don't want repetition of data and there isn't any connection between table a and b it can't be done without some union or similar
Assume you have these tables:
+----------------------------+
| PRODUCTS |
+------+-------------+-------+
| code | name | price |
+------+-------------+-------+
| 1 | Bike Helmet | 99.99 |
| 2 | Shirt | 19.99 |
+------+-------------+-------+
+-------------------+
| CATEGORIES |
+------+------------+
| code | category |
+------+------------+
| 1 | Sports |
| 1 | Cycling |
| 1 | Protection |
| 2 | Men |
| 2 | Clothing |
+------+------------+
Here is a query based on another SO answer, that would match your desired result, if my interpretation of it is correct:
SELECT p.code, p.name, p.prize,
(SELECT category FROM categories c WHERE c.code = p.code LIMIT 0, 1) as category1,
(SELECT category FROM categories c WHERE c.code = p.code LIMIT 1, 1) as category2,
(SELECT category FROM categories c WHERE c.code = p.code LIMIT 2, 1) as category3,
FROM products p
This is the result:
+------+-------------+-------+-----------+-----------+------------+
| code | name | price | category1 | category2 | category3 |
+------+-------------+-------+-----------+-----------+------------+
| 1 | Bike Helmet | 99.99 | sports | cycling | protection |
| 2 | Shirt | 19.99 | men | clothing | NULL |
+------+-------------+-------+-----------+-----------+------------+
It is not possible, though, to have a dynamic number of categories in the result. In this case I limited the number to 3, like in your question. There might still be a solution with better performance. Also, this is obviously a nested query and therefore probably not suited for your needs. Still, it's the best I could come up with.
JOIN
There is also the SQL JOIN clause, which might be what you are looking for:
SELECT *
FROM products
NATURAL JOIN categories
You would end up with this result:
+------+-------------+-------+------------+
| code | name | price | category |
+------+-------------+-------+------------+
| 1 | Bike Helmet | 99.99 | sports |
| 1 | Bike Helmet | 99.99 | cycling |
| 1 | Bike Helmet | 99.99 | protection |
| 2 | Shirt | 19.99 | men |
| 2 | Shirt | 19.99 | clothing |
+------+-------------+-------+------------+
I guess that you will have to do two separate queries.
One to retrieve products, one to retrieve the product categories.
Then use any scripting language (like PHP) to achieve what you want with the results (display, export, whatever).
I'm new to relational sql. I'm trying to figure out a query to return the names of customers who have more than one type of account.
customers:
+------------+--------------+
| cid | Name |
+------------+--------------+
| 1 | Bob |
| 2 | John |
| 3 | Jane |
+------------+--------------+
accounts:
+------------+--------------+
| aid | type |
+------------+--------------+
| 1 | Checking |
| 2 | Saving |
| 3 | CD |
+------------+--------------+
transactions:
+------------+--------------+--------------+
| tid | cid | aid |
+------------+--------------+--------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 3 |
| 5 | 3 | 1 |
+------------+--------------+--------------+
With these tables, the query should return Bob and John. I'm having some trouble with how to write such a query. More specifically, how do I keep count of how many accounts a customer has and how do I compare if the accounts are different without adding a new column to the table?
Okay, this seems to work in SQL Fiddle with my test data structure. Try it out with your real data structure and see if it gives you what you're looking for.
SELECT name FROM customers c WHERE EXISTS(
SELECT DISTINCT aid FROM transactions
WHERE cid = c.cid
HAVING COUNT(DISTINCT aid)>1
)