Count across multiple columns - php

I want to find in Dx1, Dx2, Dx3 add the number of times the same category and group repeats the name of the category.
Table Categories:
ID Name
1 A
2 B
Table Dx:
ID Dx 1 Dx 2 Dx 3
1 1 1 1
2 1 1 2
Result query:
Category_name Count_dx*
A 5
B 1
Thanks.

I am giving the answer although your question seems implicit.
SELECT
Categories.Name,
COUNT(*) AS Count_dx
FROM Categories
INNER JOIN
(
SELECT
Dx1 dx_val
FROM Dx
UNION ALL
SELECT
Dx2 dx_val
FROM Dx
UNION ALL
SELECT
Dx3 dx_val
FROM Dx
) AS t
ON Categories.ID = t.dx_val
GROUP BY t.dx_val;
Probably you want to get the count of category IDs (for each category) across the three columns (Dx1, Dx2 and Dx3) in Dx table. If so then the above query does the job.

Related

Mysql join two tables with sum of quantity

Q : I am trouble to do following task in mysql query.
Task is get all products (If product is duplicate than sum of it's qty) and deduct wastage stock (If wastage product is duplicate than sum of it's qty).
I have two tables like,
1) manage_stock
2) manage_wastage
manage_stock
=> This table has p_id(Product ID) and many rows with product duplication's.
p_id p_name p_qty
1 Pro-1 10
2 Pro-2 15
3 Pro-3 8
1 Pro-1 15
manage_wastage
=> This table has p_id(Product ID) of manage_stock table. It is also many rows with product duplication's.
p_id w_qty
1 2
1 4
3 5
Desired Output
p_id p_name p_qty w_qty final_qty
1 Pro-1 20 6 14
2 Pro-2 15 0 15
3 Pro-3 8 5 3
Thank you very much.
You just have to compute the difference between the stock quantity and the wastage
SELECT s.p_id, s.p_name, SUM(p_qty), SUM(w_qty), SUM(p_qty) - SUM(w_qty) as final_qty
FROM manage_stock s
LEFT OUTER JOIN manage_wastage w
ON s.p_id = w.p_id
GROUP BY s.p_id, s.p_name
try this one
SELECT s.p_id, s.p_name, SUM(p_qty),SUM(ifnull(w_qty, 0)),SUM(p_qty - ifnull(w_qty, 0)) as total
FROM manage_stock s
left outer JOIN manage_wastage w
ON s.p_id = w.p_id
GROUP BY s.p_name
its work
SELECT ms.p_id ,GROUP_CONCAT(ms.p_name)p_name ,SUM(ms.p_qty) p_qty ,SUM(mw.w_qty) w_qty,SUM(ms.p_qty)-SUM(mw.w_qty) final_qty FROM manage_stock ms
INNER JOIN manage_wastage mw on ms.p_id =mw.p_id
GROUP BY ms.p_id
Try above code.
As p_name always unique with p_id GROUP_CONCAT() only returns single name.

mysql return same rows union

In my database i have categories, offers and coupons. i would like to count offers and coupons that exist in each category. when i use union it returns the same category twice.
i have the below query that returning same category rows with same name. i try to use union distinct but it does not work.
(SELECT
cat1.id AS cat1id, cat1.title AS title,
count(offers.id) AS offercounter
FROM cat1
INNER JOIN offers
ON offers.category=cat1.title
GROUP BY cat1.id
order by cat1.order)
UNION
(SELECT
cat1.id AS cat1id, cat1.title AS title,
count(coupons.id) AS couponscounter
FROM cat1
INNER JOIN coupons
ON coupons.category=cat1.title
GROUP BY cat1.id
order by cat1.order)
the result
cat1id title offercounter
2 Food 5388
23 Clothes 6000(this is offers)
32 Technology 499
40 Clothes 4(this is coupons)
i would like clothes to be (offercounter + couponscounter).
example: clothes=6004 and not two different rows
the desired result would be :
cat1id title offercounter
2 Food 5388
23 Clothes 6004(offers+coupons)
32 Technology 499
Alternative avoiding unions or sub queries is to use a couple of LEFT OUTER JOINS, and count the distinct ids from each table:-
SELECT cat1.id AS cat1id,
cat1.title AS title,
COUNT(DISTINCT offers.id) + COUNT(DISTINCT coupons.id) AS offercounter
FROM cat1
LEFT OUTER JOIN offers ON offers.category = cat1.title
LEFT OUTER JOIN coupons ON coupons.category = cat1.title
GROUP BY cat1.id AS cat1id,
cat1.title AS title
EDIT
A left outer join will return a row of nulls when there is no matching row.
For example if there was a row on cat1 with a matching row on offers but no matching row on coupons then the resulting row would consist of the row from cat1, the row from offers and the fields from coupons would be null.
This SQL will get every combination of matching rows. So if you had:-
cat1 fields offers fields coupons fields
id title id category id category
1 fred 99 fred 77 fred
1 fred 99 fred 88 fred
1 fred 100 fred 77 fred
1 fred 100 fred 88 fred
2 burt 120 fred NULL NULL
2 burt 121 fred NULL NULL
Hence the count uses DISTINCT to only could each id within a category once. As COUNT(field name) only counts non null values, with this example data for the 2nd category the count from coupons will be 0.
Union returns distinct rows. Your returned rows are distinct indeed. What you need to do to get your desired result is aggregate after unioning.
select min(cat1id) as cat1id, title, sum(offercounter) as offercounter
from
(your_query) as subquery
group by title
replace your_query with your existing query
Why don't you simple sum up the offercounter and use group by with order by cat1id.
SELECT cat1id,title,sum(offercounter) as offercounter
FROM offers GROUP BY title ORDER BY cat1id
View : SQL Fiddle
Output :
cat1id title offercounter
2 Food 5388
23 Clothes 6004
32 Technology 499
May be this can help.
SELECT cat1.id AS cat1id, cat1.title AS title ,((SELECT COUNT(offers.id) FROM offers WHERE offers.category=cat1.title)+(SELECT COUNT(coupons.id) FROM coupons WHERE coupons.category=cat1.title)) AS offercounter
FROM cat1

Selecting rows on Unique Pairs of columns from mysql Table

I have a Table table .
Now this has three columns table_id,content_id,content_type
What i want is to SELECT rows based on unique pairs of columns.
Say For example i have rows like this-->
id|content_id|content_type|
1 1 shirt
2 1 trouser
3 4 skirt
4 4 shirt
5 3 trouser
6 5 jeans
7 1 trouser
8 5 jeans
I want a query which selects Rows with id->1,2,3,4,5,6.
Rows with id->7,8 are not to be selected
Therefore it concludes that i dont want to select complete Duplicates of Rows
You can use a self join to pick a minimum row per group
select t.* from
test t
join (
select min(id) id ,content_id,content_type
from test
group by content_id,content_type
) t1
on(t.id = t1.id
and t.content_id = t1.content_id
and t.content_type = t1.content_type)
Demo
or if there are only these 3 columns in your table then you can simply use min()
select min(id) id ,content_id,content_type
from test
group by content_id,content_type
Demo
This is mysql-specific : If you use the GROUP BY function without using aggregate functions, the group by clause will behave as distinct, and pick up the first distinct row.
select id, content_id, content_type from test group by content_id, content_type order by id
Demo

get SUM of another row of GROUP BY'd rows

I have this table:
This selection is is duplicated many times for different var_lines (which pretty much work as one row of data, or respondent for a survey) and set_codes (different survey codes).
With this query:
SELECT
*, COUNT(*) AS total
FROM
`data`
WHERE
`var_name` = 'GND.NEWS.INT'
AND(
`set_code` = 'BAN11A-GND'
OR `set_code` = 'BAN09A-GND'
OR `set_code` = 'ALG11A-GND'
)
AND `country_id` = '5'
GROUP BY
`data_content`,
`set_code`
ORDER BY
`set_code`,
`data_content`
The query basically counts the number of answers for a specific question. Then groups them survey (set_code).
What I need is for each of the grouped data_content answers for GND.NEWS.INT to also show the SUM of all the corresponding GND_WT with the same var_line.
For example if I had this:
data_id data_content var_name var_line
1 2 GND.NEW.INT 1
2 1.4 GND_WT 1
3 2 GND.NEW.INT 2
4 1.6 GND_WT 2
5 3 GND.NEW.INT 3
6 0.6 GND_WT 3
I would get something like this:
data_id data_content var_name var_line total weight
1 2 GND.NEW.INT 1 2 3
5 3 GND.NEW.INT 3 1 0.6
Thanks for any help.
Your requirements are not exactly clear, but I think the following gives you what you want:
select d1.data_id,
d1.data_content,
d1.var_name,
d1.var_line,
t.total,
w.weight
from data d1
inner join
(
select data_content,
count(data_content) Total
from data
group by data_content
) t
on d1.data_content = t.data_content
inner join
(
select var_line,
sum(case when var_name = 'GND_WT' then data_content end) weight
from data
group by var_line
) w
on d1.var_line = w.var_line
where d1.var_name = 'GND.NEW.INT'
See SQL Fiddle with Demo
This Query can be suitable for your specific example:
select st.data_id,
st.data_content,
st.var_name,
st.var_line,
count(st.data_id) as total,
sum(st1.data_content) as weight
from data st
left join data st1 on st1.var_name = 'GND_WT' AND st1.var_line=st.var_line
where st.var_name='GND.NEW.INT'
group by st.data_content
Regards,
Luis.

Help with limiting a joined mysql database query

I have written a query which returns all records with some many-to-many joins correctly for the entire set or an individual article using WHERE a.id = ?
SELECT a.id, date_added, title, content, category_id, person_id, organization_id, c.name AS category_name, firstname, lastname, o.name AS organization_name
FROM articles AS a
LEFT OUTER JOIN articles_categories AS ac ON a.id=ac.article_id
LEFT OUTER JOIN categories AS c ON c.id=ac.category_id
LEFT OUTER JOIN articles_people AS ap ON a.id=ap.article_id
LEFT OUTER JOIN people AS p ON p.id=ap.person_id
LEFT OUTER JOIN articles_organizations AS ao ON a.id=ao.article_id
LEFT OUTER JOIN organizations AS o ON o.id=ao.organization_id
ORDER BY date_added
BUT!
I've hit a brick wall trying to work out how to limit the articles to a specific number of IDs, for working with pagination.
I'm ideally trying to use as simple and clear SQL statements as possible because I'm using the codeigniter framework with their active record class.
http://codeigniter.com/user_guide/database/active_record.html
Would really appreciate some help as I don't want to revert to using multiple queries for this as I've tried to reduce it down to a single query for database efficiency.
Have search around and tried some alternatives but nothing seems to work. Many thanks!
For example the results I return are like this
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
1 test 2 1 1
1 test 1 2 1
1 test 1 1 2
1 test 5 1 1
1 test 8 1 1
1 test 1 4 1
1 test 1 4 2
1 test 1 1 1
2 test 2 2 1 1
2 test 2 1 2 1
2 test 2 1 1 2
2 test 2 5 1 1
2 test 2 8 1 1
2 test 2 1 4 1
2 test 2 1 4 2
I need the results like this so that I can create sub-arrays in the php like this:
$articles = $query->result_array();
$output = array();
foreach ($articles as $article) {
// set up article details
$article_id = $article['id'];
// add article details
$output[$article_id]['article_id'] = $article_id;
$output[$article_id]['date_added'] = $article['date_added'];
$output[$article_id]['title'] = $article['title'];
$output[$article_id]['content'] = $article['content'];
// set up people details and add people array with details if exists
if (isset($article['person_id'])) {
$person_id = $article['person_id'];
$output[$article_id]['people'][$person_id]['person_id'] = $person_id;
$output[$article_id]['people'][$person_id]['lastname'] = $article['lastname'];
$output[$article_id]['people'][$person_id]['firstname'] = $article['firstname'];
}
// set up organizations details and add organizations array with details if exists
if (isset($article['organization_id'])) {
$organization_id = $article['organization_id'];
$output[$article_id]['organizations'][$organization_id]['organization_id'] = $organization_id;
$output[$article_id]['organizations'][$organization_id]['organization_name'] = $article['organization_name'];
}
// set up categories details and add categories array with details if exists
if (isset($article['category_id'])) {
$category_id = $article['category_id'];
$output[$article_id]['categories'][$category_id]['category_id'] = $category_id;
$output[$article_id]['categories'][$category_id]['category_name'] = $article['category_name'];
}
}
But if I just use LIMIT (with offset etc) 1
the results I get are
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
instead of
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
1 test 2 1 1
1 test 1 2 1
1 test 1 1 2
1 test 5 1 1
1 test 8 1 1
1 test 1 4 1
1 test 1 4 2
1 test 1 1 1
which is my desired result.
OK, so finally I worked out how it is possible.
Thought i'd include it here in case anyone else has the same problem.
Changing this line
FROM articles AS a
to this
FROM (SELECT * FROM articles LIMIT 5,3) AS a
does what I wanted.
So, why don't you use OFFSET 0,10 and LIMIT *number_of_results* in the SQL Query? (if I understood the question)
Specific number of IDs... WHERE ID IN (2,4,6,8)... ?
Are you using codeigniter's pagination?
http://codeigniter.com/user_guide/libraries/pagination.html
You can easily limit the number of records that are being returned using the MySQL LIMIT clause. This can be achieved like the following with your sample query.
SELECT a.id, date_added, title, content, category_id, person_id, organization_id, c.name AS category_name, firstname, lastname, o.name AS organization_name
FROM articles AS a
LEFT OUTER JOIN articles_categories AS ac ON a.id=ac.article_id LEFT OUTER JOIN categories AS c ON c.id=ac.category_id
LEFT OUTER JOIN articles_people AS ap ON a.id=ap.article_id LEFT OUTER JOIN people AS p ON p.id=ap.person_id
LEFT OUTER JOIN articles_organizations AS ao ON a.id=ao.article_id LEFT OUTER JOIN organizations AS o ON o.id=ao.organization_id
ORDER BY date_added
LIMIT 10
Where 10 is the number of records you wish to display. The MySQL LIMIT clause allows you to specify a limit of the number of records and an initial offset. Like so:
LIMIT <offset>,<limit>
In your case <offset> would be the current page * the number of records on a page. <limit> would be the number of records you would like to display per page.

Categories