Introduction
I have the following sql tables. Every entity has one-to-many variations and every variation has one-to-many entities.
- ENTITY (ID INTEGER PRIMARY KEY, ID_ENTITY TEXT NOT NULL, wiki_title TEXT);
- VARIATIONS (ID INTEGER PRIMARY KEY NOT NULL, NAME TEXT, LANGUAGE TEXT, TYPE TEXT);
- VAR_ENTITE (ID_ENTITE TEXT NOT NULL, ID_VAR INTEGER NOT NULL, PRIMARY KEY(ID_ENTITE, ID_VAR), FOREIGN KEY(ID_ENTITE) REFERENCES ENTITE(ID_ENTITE), FOREIGN KEY (ID_VAR) REFERENCES VARIATIONS(ID));
question
How can I use sql language in order to count the number of variations per entity ?
List of tables with sample data
Entity
Table entity has 3 records
ID Id_ENTITE wiki_title
48398|m.0nkkw65|Record label|
48399|m.0cp5rvm|Location|
117142|m.0n479hn|Yuika_Sugasawa|
Var_ENTITE
Table Var_entite shows that Entities m.0nkkw65 and m.0760j5n have only 1 variation whereas m.0n479hn has 2 variations.
Id_entity Id_var
m.0nkkw65|109628
m.0760j5n|109631
m.0n479hn|261081
m.0n479hn|261082
Variations
109628|A.G. Producciones|es|Label
109631|Screven County Middle School|en|Label
261081|Yuika Sugasawa|en|Label
261082|菅澤優衣香|ja|Label
Results
As a result I should be able to see the following:
m.0nkkw65: 1
m.0760j5n: 1
m.0n479hn: 2
This will work. Just count the number of variations associated with entity name like 'Angela Merkel'
SELECT COUNT(v.ID) AS Number_OF_Variations
FROM Variation v
INNER JOIN VAR_ENTITE ve ON ve.ID_VAR =v.ID
INNER JOIN ENTITY e ON e.ID=ve.ID_ENTITE
WHERE e.wiki_title = 'Angela Merkel'
Looks like a simple join, with a COUNT. Guessing at how your tables join together:-
SELECT a.id, a.id_entite, COUNT(c.id) AS variation_count
FROM entity a
LEFT OUTER JOIN var_entite b
ON a.id = b.id_entite
LEFT OUTER JOIN variations c
ON b.id_var = c.id
GROUP BY a.id, a.id_entite
Note that you might not need to join to the variations table (can just use the id from the var_entite table if there is nothing else you need from variations). Also if all items have at least one variation you could probably switch to using INNER JOINs rather than LEFT OUTER JOINs
Related
I am still a beginner and i searched in google ,read w3schools and couldn't get how to do it the following thing.
i want to create view from the info in cases field
AS you saw these are the info inside the tables (names,depart,idcards)
this the table i want to get the data from i made all the column start with id_* as foreign key for the PK in the previous tables
note:id_case is the PK of the table, id_dep is for department,id name is for name,id_complaint
This is just a bunch of joins:
CREATE VIEW viewname AS
SELECT *
FROM cases AS c
JOIN names AS n ON c.id_name = n.id
JOIN depart AS d ON c.id_dep = d.id
JOIN complaint AS cm ON c.id_complaint = cm.id
...
Note that if there are any column names that are the same among any of the tables, you'll need to list them explicitly in the SELECT list and assign distinct aliases to them. See MySQL JOIN tables with duplicate column names
I'm trying to make a code question website, like CodeChef.
So far, I have two tables, problems and submissions.
problems consists of a single id field which is auto_incremented. (It really has more fields, but they are not relevant.)
submissions consists of an id field which is auto_incremented, a problem_id field which is foreign key-ed to problems.id, and a bool correct field.
Here are their (simplified) creation statements:
create table problems
(
id bigint auto_increment primary key not null,
/* more fields that are unimportant */
);
create table submissions
(
id bigint auto_increment primary key not null,
problem_id bigint not null,
correct bool not null,
/* more fields */
foreign key (problem_id) references problems(id)
);
Now, what I'm trying to do is the following:
For each id in problems, return a row consisting of that ID, the number of correct submissions for that problem, and the number of total submissions for that problem.
Basically, I want to use the following query:
select
problems.id,
sum(submissions.correct),
count(submissions.id)
from submissions inner join problems
on submissions.problem_id=problems.id and problems.id=[problem_id];
where [problem_id] goes over every id in problems.
It seems like I need to use a sub-query, but I tried it and it did not work at all.
How do I create a query to return these results?
Your query has some defaults.
You do not specify the grouping criteria for the aggregates you use
you join, this is a 'for each' per se. You don't need anything else than the join condition you already specified
Your join should be a left join since maybe there's no correct submission for your problem, leading to 0 results at all in case of an inner join.
This is my proposition:
SELECT
p.id,
SUM(IF(s.correct, 1, 0)) AS correct_submissions,
COUNT(s.id) AS total_submissions
FROM problems p
LEFT JOIN submissions s ON p.id = s.problem_id
GROUP BY
p.id
All you need for your query is a group by clause:
select problems.id,
sum(submissions.correct),
count(submissions.id)
from submissions inner join
problems
on submissions.problem_id=problems.id
group by problems.id;
try
select
problems.id,
sum(submissions.correct),
count(submissions.id)
from submissions inner join problems
on submissions.problem_id=problems.id
where problems.id=[problem_id]
group by problems.id;
I have the following two database tables:
`membership_members` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` tinytext NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
)
`membership_payments` (
`date` date NOT NULL,
`amount` int(11) NOT NULL,
`member` int(11) NOT NULL,
KEY `member` (`member`)
)
I wish to list all the members, and for each of them I would like to show the list of all the payments by that member. The membership_payments.member column is a foreign key membership_members.id (this is MySQL so I cannot explicitly specify a foreign key). Notice that I do want to list a member even if he doesn't have any payments.
So something like:
* John Smith
- 2012-05-06 $100
- 2012-01-02 $100
* Brian Jones
* Mike Jackson
- 2012-09-02 $50
I have tried with this query:
SELECT id, name, active, date, amount
FROM `membership_members`,
`membership_payments`
WHERE membership_members.id = member
This of course gives me tha data I need, but not exactly how I need it as it returns a row for each payment. That means that I later have to group the rows (in PHP) by member id so that I don't list a member multiple times. I can do that, but I believe that it would be easier and faster to do it in SQL. Also, this query only gives me users which have payments with their id.
I feel that this should be simple, but last time I did anything but the most simple stuff in SQL was 6-7 years ago.
EDIT:
LEFT OUTER JOIN suggested in one of the answers solves the issue with the "missing" members. But what is the best way of grouping results by member IDs? I know there is a GROUP BY clause, but it doesn't give me all the payments for the given member, only one. I suppose I can run a new payments query for each member, but I fear this would be very inefficient (we have around 300-400 members).
You'll need to JOIN the two tables based on referencing key columns.
SELECT id, name, active, date, amount
FROM membership_members
LEFT OUTER JOIN membership_payments
ON membership_members.id = membership_payments.member;
I chose LEFT OUTER JOIN so that the members without payments are also shown.
For more info on joins check http://dev.mysql.com/doc/refman/5.0/en/join.html
EDIT
Use ORDER BY membership_members.id to get records ordered by a certain column.
Grouping does not behave like sorting. GROUPING merges all records by the column you provided. ORDER BY sorts
use LEFT JOIN
basically, what you are doing now is an INNER JOIN. INNER JOIN only displays a records if it has atleast one record on each table. But LEFT JOIN operates differently. It displays all records on the Lefthand side table whether it has matching record or not on the righthand side table.
SELECT id, name, active, date, amount
FROM `membership_members` a
LEFT JOIN `membership_payments` b
ON a.ID = b.member
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Take a look at GROUP_CONCAT MySQL clause.
Example
OR
You can use CONCAT.
Example
SELECT CONCAT(`membership_payments.date`, ' ', `membership_payments.amount`)
FROM `membership_members`
LEFT OUTER JOIN membership_payments
ON membership_members.id = membership_payments.member;
It's my first time with mysql and I need some help. I couldn't find any solution to this probably because it's too easy or I'm too noob to look it up properly yet.
I want to make a query from multiple tables from my test database. Let's say tables are:
category (*id_category, *id_product)
product (*id_product, id_category, id_supplier, id_manufacturer)
manufacturer (*id_manufacturer, name)
supplier (*id_supplier, name)
The columns with * are integer primary key not null with auto_increment(starting from 1). The other id columns are just integer foreign keys(default null).
I need a query also including rows with null id_manufacturer and/or id_supplier on the product table. Those empty fields in the product table return value '0', so when I make a query like
SELECT category.id_product, manufacturer.name, supplier.name
FROM category, product, manufacturer, supplier
WHERE category.id_category = product.id_category AND manufacturer.id_manufacturer = product.id_manufacturer AND supplier.id_supplier = product.id_supplier;
None of the rows with null values(0)are shown.
I'd like you to point me in the most clean and efficient way to do it without changing table properties. Any help would be very much appreciated.
You need to use Left Join then.
SELECT category.id_product, manufacturer.name, supplier.name, P.ID_PRODUCT
FROM product
LEFT JOIN category C
ON C.id_category = P.id_category
LEFT JOIN manufacturer M
ON M.id_manufacturer = P.id_manufacturer
LEFT JOIN supplier S
ON S.id_supplier = P.id_supplier;
These will give all the rows of product table even if it has no corresponding row from other tables.
I want to get articles and all tag names which they're connected to from a MySQL database. My SQL code:
CREATE TABLE articles (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
)
CREATE TABLE tags (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(25) NOT NULL,
PRIMARY KEY (id)
)
CREATE TABLE connections (
art_id INT UNSIGNED NOT NULL,
tag_id INT UNSIGNED NOT NULL
);
Should I perform several queries or make single big one? How can I achive that? I tried to play with JOIN, but it seems it cannot be done that way.
PS. I've been searching, but there is no EXACT question on SO.
select a.id, group_concat(t.name) as tags
from articles a
left join connections c on c.art_id = a.id
left join tag t on t.id = c.tag_id
group by a.id
This query returns 1 row per article, and group_concat() will return the names of all connected tags as a comma delimited list (or null if there are no connected tags).
You're off to a great start - but there are a few things that can be optimized here.
Let's also assume your Article table has an ID and a Title field (just to add some spice to this query).
To simply answer your questions:
Select a.ID "ID", a."Title" "Title", t.Name "Tag_Name"
From connections c
Left Join article a
on a.id = c.art_id
Left Join tags t
on t.id = c.tag_id
-- If you want to filter on a certain article ID
WHERE a.id = #SomeArticleParam
I would really advise a couple things to optimize these tables:
Since connections directly links articles and tags, I would add foreign key references to the connections table. Here is a good link: foreign key link.
Index your connections table - this will allow faster queries when referencing specific tags or articles. A Unique index will help prevent adding duplicate article/tag pairs in the connections table. Here is a good link to get you started: index link.
try this
select a.(*),t.name from articles a
inner join connection c on a.id=c.art_id
inner join tags t on c.tag_id=t.id
SELECT articles.*,tags.* FROM articles , tags,connections
where tags.id=connections.tag_id and articles.id=connections.art_id