I have 3 Tables
campaign1 (TABLE)
id campaign_details
1 'some detail'
campaign2 (TABLE)
id campaign_details
1 'some other detail'
campaign_list (TABLE)
id campaign_table_name
1 'campaign1'
2 'campaign2'
Campaign list table contains the table name of the two tables described above. I want to Select from the Campaign List table and get the record count using the table name i get from this select
For eg.
using select i get campaign1(Table name). Then i run select query on campaign1 to count number of records.
What i'm doing right now is .
-Select from campign_list
-loop through all campaign_table_names and run select query individually
Is there a way to do this using a single query
something like this
select campaign_name,(SELECT COUNT(*) FROM c.campaign_name) as campcount from campaign_list c
SQLFiddle : http://sqlfiddle.com/#!9/b766d/2
It's not possible inside a single query to build it dynamically but it's possible to cheat. Especially if there are only two linked tables.
I've listed two options
left outer join both tables
select campaign_name,
coalesce(c1.campaign_details, c2.campaign_details)
from campaign_list c
left join campaign1 c1 using (id)
left join campaign2 c2 using (id);
union all two different selects
select campaign_name,
campaign_details
from campaign_list c
join campaign1 c1 using (id)
union all
select campaign_name,
campaign_details
from campaign_list c
join campaign2 c2 using (id);
sqlfiddle
Combine your campaign tables to 1 table and add an column named 'type' (int).
campaign_items tables:
item_id item_details item_type
1 'some detail' 1
2 'some detail' 1
3 'some other detail' 2
4 'some other detail' 2
campaign_lists table
campaign_id campaign_name
1 'campaign1'
2 'campaign2'
Then you can use the following select statement:
SELECT campaign_name, (SELECT COUNT(*) FROM campaign_items WHERE item_type = campaign_id) as campaign_count
FROM campaign_lists
Oops, writing took me so long that you got this answered by Colin Raaijmakers already. Well, I'll post my answer anyway in spite of being more or less the same answer. Maybe my elaboration helps you see the problem.
Your problem stems from a bad database design. A database is made to order data and its relations. A CD database holds albums, songs, artists, etc. A business database may hold items, warehouses, sales and so on. Your database holds table names. [... time for thinking :-) ]
(When writing a DBMS you would want to store table names, column names, constraints etc., but I guess I am right supposing that you are not writing a new DBMS.)
So create tables that deal with your actual data. E.g.:
campain_type (id_campain_type, description, ...)
campain (id_campain, id_campain_type, campain_date, ...)
campain_type
id_campain_type description
1 Type A
2 Type B
3 Type C
campain
id_campain id_campain_type date
33 1 2015-06-03
85 2 2015-10-23
97 2 2015-12-01
query
select
ct.description,
(select count(*) from campain c where c.id_campain_type = ct.id_campain_type) as cnt
from campain_type ct;
result
description cnt
Type A 1
Type B 2
Type C 0
Related
I want to join columns from multiple tables to one column, in my case column 'battery_value' and 'technical_value' into column 'value'. I want to fetch data for only given category_ids, but because of UNION, I get data from other tables as well.
I have 4 tables:
Table: car
car_id model_name
1 e6
Table: battery
battery_category_id car_id battery_value
1 1 125 kW
Table: technical_data
technical_category_id car_id technical_value
1 1 5
3 1 2008
Table: categories
category_id category_name category_type
1 engine power battery
1 seats technical
3 release year technical
From searching, people are suggesting that I use union to join these columns. My query now looks like this:
SELECT CARS.car_id
category_id,
CATEGORIES.category_name,
value,
FROM CARS
left join (SELECT BATTERY.battery_category_id AS category_id,
BATTERY.car_id AS car_id,
BATTERY.value AS value
FROM BATTERY
WHERE `BATTERY`.`battery_category_id` IN (1)
UNION
SELECT TECHNICAL_DATA.technical_category_id AS category_id,
TECHNICAL_DATA.car_id AS car_id,
TECHNICAL_DATA.value AS value
FROM TECHNICAL_DATA
WHERE `TECHNICAL_DATA`.`technical_category_id` IN (3))
tt
ON CARS.car_id = tt.car_id
left join CATEGORIES
ON category_id = CATEGORIES.id
So the result I want is this, because I only want to get the data where category_id 1 is in battery table:
car_id category_id category_name technical_value
1 1 engine power 125 kW
1 3 release year 2008
but with the query above I get this, category_id 1 from technical table is included which is not something I want:
car_id category_id category_name value
1 1 engine power 125 kW
1 1 seats 125 kW
1 3 release year 2008
How can get exclude the 'seats' row?
For the results you want, I don't see why the cars table is needed. Then, you seem to need an additional key for the join to categories based on which table it is referring to.
So, I suggest:
SELECT tt.*, c.category_name
FROM ((SELECT b.battery_category_id AS category_id,
b.car_id AS car_id, b.value AS value,
'battery' as which
FROM BATTERY b
WHERE b.battery_category_id IN (1)
) UNION ALL
(SELECT td.technical_category_id AS category_id,
td.car_id AS car_id, td.value AS value,
'technical' as which
FROM TECHNICAL_DATA td
WHERE td.technical_category_id IN (3)
)
) tt LEFT JOIN
CATEGORIES c
ON c.id = tt.category_id AND
c.category_type = tt.which;
That said, you seem to have a problem with your data model, if the join to categories requires "hidden" data such as the type. However, that is outside the scope of the question.
I have two tables
1. studentprofile
sud_id name
1 kp
2 kishan
3 raj
2. fee_generate
fee_id stud_id fee_balance name
1 1 0 kp
2 2 10 kishan
I want to show those students whose fee is not submitted or have any balance, which means that I want to show is as following
kishan and raj
I am not able to write the query with any join. My second problem is that name columns are common in both tables.
So the selected name column should come from studentprofile table and order by name from studentprofile table.
You need to left join the fee_generate table on the student_profile table and include those records where the fee_generate.student_id is null (not submitted) or the balance is over 0:
select s.* from student_profile s
left join fee_generate f on s.stud_id=f.stud_id
where f.stud_id is null or f.balance>0
order by f.name
I got 3 tables in my MYSQL bases and I have to compare how many time there are each user_ID in each of the 2 first table (table 1 and table 2)
here is my table 1:
user_ID
A
B
A
D
...
here is my table 2 :
user_ID
A
C
A
...
here is my table 3 (with link between user_ID and nickname) :
user_ID // nickname
A // Bob
B // Joe
C // Tom
...
I would like to get a result like this:
Nickname // count occurrences from Table 1 // count occurrences from table 2
Bob // 1 // 2
Joe // 4 // 0
Tom // 0 // 2
I did not succeed for instant to count separately from each table, I got a global result for each nickname :(
Could you help me to find the right MYSQL request ?
- ...
This type of query is a little tricky, because some names may not be in the first table and others may not be in the second. To really solve this type of problem, you need to pre-aggregate the results for each query. To get all the names, you need a left outer join:
select t3.name, coalesce(cnt1, 0) as cnt1, coalesce(cnt2, 0) as cnt2
from table3 t3 left outer join
(select name, count(*) as cnt1
from table1
group by name
) t1n
on t3.name = t1n.name left outer join
(select name, count(*) as cnt2
from table2
group by name
) t2n
on t3.name = t1n.name;
I'm facing a problem while trying to retrieve all productIDs from a table if they match all items in an array, in this case, return products only if they contain every ingredient the user searched for.
Table looks like this
ID produktID ingredientID
----------------------------
1 418 1
2 418 2
3 418 3
4 416 4
5 411 1
6 411 5
7 411 6
I join this table from a products table where the main information is stored. The aim of the query should be to retreive a productID only when all ingredientIDs match with the given array. I've tried using WHERE ingredientID IN(1,5,6) but it always turns out to be an OR statement, returning every ID where any of the ingredients are matched.
So for example, if I pass (1,5,6) or (5,6) the product ID 411 should be returned, but if I pass (2,5,6) it should not.
The query I tried looks like this (simplified, it's part of a 5 way join to other relations like brands and catgories)
SELECT productID FROM products_ingredients_mm WHERE ingredientID IN (1,5,6) GROUP BY productID
but the result contains 418 aswell. How do I get it to match?
I hope I was able to describe the problem in an understandable way, it's really hard for me to wrap my head around it to ask a question.
This is called Relational Division.
SELECT produktID
FROM tableName
WHERE ingredientID IN (1,5,6)
GROUP BY produktID
HAVING COUNT(*) = 3
SQLFiddle Demo
If a unique constraint was not enforce on ingredientID for every produktID, then you need to use DISTINCT
SELECT produktID
FROM tableName
WHERE ingredientID IN (1,5,6)
GROUP BY produktID
HAVING COUNT(DISTINCT ingredientID) = 3
SQLFiddle Demo
Other Source
Relational Division
Try this:
SELECT pi.productID, p.productName
FROM products_ingredients_mm pim
INNER JOIN products p ON pim.productID = p.productID
WHERE ingredientID IN (1,5,6)
GROUP BY productID
HAVING COUNT(DISTINCT ingredientID) = 3
For simplicity, I will give a quick example of what i am trying to achieve:
Table 1 - Members
ID | Name
--------------------
1 | John
2 | Mike
3 | Sam
Table 1 - Member_Selections
ID | planID
--------------------
1 | 1
1 | 2
1 | 1
2 | 2
2 | 3
3 | 2
3 | 1
Table 3 - Selection_Details
planID | Cost
--------------------
1 | 5
2 | 10
3 | 12
When i run my query, I want to return the sum of the all member selections grouped by member. The issue I face however (e.g. table 2 data) is that some members may have duplicate information within the system by mistake. While we do our best to filter this data up front, sometimes it slips through the cracks so when I make the necessary calls to the system to pull information, I also want to filter this data.
the results SHOULD show:
Results Table
ID | Name | Total_Cost
-----------------------------
1 | John | 15
2 | Mike | 22
3 | Sam | 15
but instead have John as $20 because he has plan ID #1 inserted twice by mistake.
My query is currently:
SELECT
sq.ID, sq.name, SUM(sq.premium) AS total_cost
FROM
(
SELECT
m.id, m.name, g.premium
FROM members m
INNER JOIN member_selections s USING(ID)
INNER JOIN selection_details g USING(planid)
) sq group by sq.agent
Adding DISTINCT s.planID filters the results incorrectly as it will only show a single PlanID 1 sold (even though members 1 and 3 bought it).
Any help is appreciated.
EDIT
There is also another table I forgot to mention which is the agent table (the agent who sold the plans to members).
the final group by statement groups ALL items sold by the agent ID (which turns the final results into a single row).
Perhaps the simplest solution is to put a unique composite key on the member_selections table:
alter table member_selections add unique key ms_key (ID, planID);
which would prevent any records from being added where the unique combo of ID/planID already exist elsewhere in the table. That'd allow only a single (1,1)
comment followup:
just saw your comment about the 'alter ignore...'. That's work fine, but you'd still be left with the bad duplicates in the table. I'd suggest doing the unique key, then manually cleaning up the table. The query I put in the comments should find all the duplicates for you, which you can then weed out by hand. once the table's clean, there'll be no need for the duplicate-handling version of the query.
Use UNIQUE keys to prevent accidental duplicate entries. This will eliminate the problem at the source, instead of when it starts to show symptoms. It also makes later queries easier, because you can count on having a consistent database.
What about:
SELECT
sq.ID, sq.name, SUM(sq.premium) AS total_cost
FROM
(
SELECT
m.id, m.name, g.premium
FROM members m
INNER JOIN
(select distinct ID, PlanID from member_selections) s
USING(ID)
INNER JOIN selection_details g USING(planid)
) sq group by sq.agent
By the way, is there a reason you don't have a primary key on member_selections that will prevent these duplicates from happening in the first place?
You can add a group by clause into the inner query, which groups by all three columns, basically returning only unique rows. (I also changed 'premium' to 'cost' to match your example tables, and dropped the agent part)
SELECT
sq.ID,
sq.name,
SUM(sq.Cost) AS total_cost
FROM
(
SELECT
m.id,
m.name,
g.Cost
FROM
members m
INNER JOIN member_selections s USING(ID)
INNER JOIN selection_details g USING(planid)
GROUP BY
m.ID,
m.NAME,
g.Cost
) sq
group by
sq.ID,
sq.NAME