MySQL count rows with two duplicate column values - php

I would like to count rows with the same serv AND spec. The below query counts the rows correctly:
SELECT *, COUNT(*) AS c
FROM table1
GROUP BY serv, spec
But I would like the output displayed as such:
Original:
+-----+------+------+
| id | serv | spec |
| 500 | 1 | 4 |
| 501 | 5 | 1 |
| 502 | 1 | 4 |
| 503 | 1 | 5 |
| 504 | 5 | 6 |
| 505 | 2 | 4 |
| 506 | 5 | 1 |
| 507 | 2 | 4 |
| 508 | 4 | 3 |
| 509 | 2 | 4 |
+-----+------+------+
Desired output:
+-----+------+------+-------+
| id | serv | spec | count |
| 500 | 1 | 4 | 2 |
| 502 | 1 | 4 | 2 |
| 503 | 1 | 5 | 1 |
| 505 | 2 | 4 | 3 |
| 507 | 2 | 4 | 3 |
| 509 | 2 | 4 | 3 |
| 508 | 4 | 3 | 1 |
| 501 | 5 | 1 | 2 |
| 506 | 5 | 1 | 2 |
| 504 | 5 | 6 | 1 |
+-----+------+------+-------+

Since MySQL doesn't support window functions, you have do the counts in a subquery, and then join this subquery to the table:
SELECT t.id, t.serv, t.spec, c.cnt
FROM
table1 t INNER JOIN (
SELECT serv, spec, COUNT(*) as cnt
FROM table1
GROUP BY serv, spec
) c ON t.serv = c.serv AND t.spec=c.spec

Related

SQL SUM() All with check from other table

Table con_projects
mysql> SELECT * FROM con_projects;
+----+---------------+---------------------+--------+
| id | project_name | project_description | status |
+----+---------------+---------------------+--------+
| 1 | Project 1 | Description IS Here | 1 |
| 2 | Project 2 | Description IS Here | 0 |
| 3 | Project 3 | Description IS Here | 1 |
| 4 | Project 4 | Description IS Here | 0 |
| 5 | Project 5 | Description IS Here | 1 |
+----+---------------+---------------------+--------+
Here status 1=active and 0=inactive
mysql> SELECT * FROM con_transactions;
+------+------+---------------------+--------+
| t_id | p_id | date | amount |
+------+------+---------------------+--------+
| 10 | 1 | 2016-02-17 19:24:05 | 1800 |
| 12 | 2 | 2016-02-18 11:40:13 | 200 |
| 17 | 3 | 2016-02-18 11:42:04 | 100 |
| 19 | 4 | 2016-02-18 11:45:43 | 1 |
| 20 | 5 | 2016-02-18 11:45:54 | 999 |
| 21 | 1 | 2016-02-18 11:46:02 | 1500 |
| 41 | 2 | 2016-02-18 17:23:14 | 500 |
| 42 | 3 | 2016-02-18 17:23:14 | 500 |
| 43 | 4 | 2016-02-18 17:23:15 | 500 |
| 44 | 5 | 2016-02-18 17:23:16 | 500 |
| 45 | 1 | 2016-02-18 17:23:16 | 500 |
| 46 | 2 | 2016-02-18 17:23:16 | 500 |
| 47 | 3 | 2016-02-18 17:23:17 | 500 |
| 48 | 4 | 2016-02-18 17:23:17 | 500 |
| 49 | 5 | 2016-02-18 17:23:18 | 500 |
| 50 | 1 | 2016-02-18 17:25:54 | 1000 |
| 51 | 1 | 2016-02-18 17:26:22 | 3000 |
| 52 | 2 | 2016-02-18 17:48:59 | 10 |
| 53 | 1 | 2016-02-18 17:48:59 | 10 |
| 55 | 1 | 2016-02-19 10:20:12 | 1000 |
+------+------+---------------------+--------+
Now I want to SUM() all amount from con_trnsactions whose p_id from con_projects status = 1
I tried this and many more
mysql> SELECT (SELECT SUM(t.amount) FROM con_transactions t WHERE p.id=t.p_id) as total FROM con_projects p WHERE status='1'
+-------+
| total |
+-------+
| 14120 |
+-------+
AND
mysql> SELECT SUM(amount) from con_transactions;
+-------------+
| SUM(amount) |
+-------------+
| 14120 |
+-------------+
Both Are Same . But The subtraction will be like this.
mysql> SELECT 1800+100+999+1500+500+500+500+500+500+1000+3000+10+1000;
+---------------------------------------------------------+
| 1800+100+999+1500+500+500+500+500+500+1000+3000+10+1000 |
+---------------------------------------------------------+
| 11909 |
+---------------------------------------------------------+
here is the all active project (con_trsaction.p_id=con_projects.id AND con_projects.status=1) id (p_id) From con_trsanction.amount
Try this:
SELECT SUM(t.amount)
FROM con_transactions t
INNER JOIN con_projects AS p ON t.p_id = p.id
WHERE p.status = 1
It's a simple join operation. Only 'active' projects will be accounted for in the summation.
SELECT SUM(amount) from con_transactions LEFT JOIN con_projects ON con_projects.id = con_transactions.p_id WHERE con_projects.status = 1;

MySQL get Related and Unrelated Records from Table in One Query

I have a user and pages table, and these two have many to many relationship between them with the bridge table user privileges. What I want to get all the pages name and only those are marked that is assigned to that user.
want some think like this
+---------+----------------------------------+
| user_id | page_name | Assigned|
+---------+----------------------------------+
| 1 | Add Project | 0 |
| 1 | Department | 0 |
| 1 | Category | 1 |
| 1 | Item | 0 |
| 1 | Units | 1 |
| 1 | Stock In | 0 |
| 1 | Stock Card Report | 1 |
+---------+------------------------+---------|
for now my query is this;
Select up.user_id, p.page_name FROM user_privileges up, pages p where p.page_id = up.page_id and up.user_id = 1;
and it returns this;
+---------+------------------------+
| user_id | page_name |
+---------+------------------------+
| 1 | Add Project |
| 1 | Department |
| 1 | Category |
| 1 | Item |
| 1 | Units |
| 1 | Stock In |
| 1 | Stock Card Report |
+---------+------------------------+
The Scheme is this;
table - user
+---------+-----------+
| user_id | user_name |
+---------+-----------+
| 4 | saif |
| 1 | admin |
| 5 | taqi |
| 2 | rashid |
+---------+-----------+
table - pages
+---------+---------------+
| page_id | page_name |
+---------+---------------+
| 2 | Page 1 |
| 3 | Page 2 |
| 5 | Page 3 |
| 6 | Page 4 |
| 7 | Page 5 |
| 8 | Page 6 |
| 9 | Page 7 |
| 10 | Page 8 |
| 11 | Page 9 |
| 13 | Page 10 |
| 14 | Page 11 |
| 15 | Page 12 |
| 16 | Page 13 |
| 18 | Page 14 |
| 19 | Page 15 |
| 20 | Page 16 |
+---------+---------------+
and table user_privalges for user_id = 1 only.
+--------------------+---------+---------+
| user_privileges_id | user_id | page_id |
+--------------------+---------+---------+
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 1 | 5 |
| 4 | 1 | 6 |
| 5 | 1 | 7 |
| 6 | 1 | 8 |
| 7 | 1 | 9 |
| 8 | 1 | 10 |
| 9 | 1 | 11 |
| 10 | 1 | 13 |
| 11 | 1 | 14 |
| 12 | 1 | 15 |
| 13 | 1 | 16 |
| 14 | 1 | 18 |
| 15 | 1 | 19 |
| 16 | 1 | 20 |
+--------------------+---------+---------+
Select up.user_id, p.page_name FROM user_privileges up, pages p where p.page_id = up.page_id and up.user_id = 1 AND up.Assigned=1;
"What I want to get all the pages name and only those are marked that is assigned to that user." So with your edit you should try something like that with case statement
SELECT up.user_id, p.page_name,
CASE
WHEN up.page_id=p.page_id THEN '1'
ELSE '0'
END AS Assigned
FROM pages p left join user_privileges up
ON p.page_id = up.page_id
WHERE up.user_id = 1;
If you are only looking for the user_id = 1 you may do something as
select
1 as user_id,
p.page_name,
case when up.page_id is not null then 1 else 0 end as `Assigned`
from pages p
left join user_privalges up on up.page_id = p.page_id and up.user_id = 1
order by p.page_id
http://www.sqlfiddle.com/#!9/06f65/5

Query MySQL To Show Counting from the table relation

i have 3 tables. 2 reference table and one table transactions.
Table puskesmas
mysql> select id,nama from puskesmas;
+----+----------------------+
| id | nama |
+----+----------------------+
| 1 | BAMBANGLIPURO |
| 2 | BANGUNTAPAN |
| 3 | BANTUL |
| 4 | DLINGO |
| 5 | IMOGIRI |
| 6 | JETIS |
| 7 | KASIHAN |
| 8 | KRETEK |
| 9 | PAJANGAN |
| 10 | PANDAK |
+----+----------------------+
Table poli
mysql> select * from poli;
+----+---------------+
| id | nama |
+----+---------------+
| 1 | BP |
| 2 | KIA |
| 3 | GIGI |
| 4 | JIWA |
+----+---------------+
Table loket
mysql> select pasien_id,poli_id,puskesmas_id from loket limit 10;
+-----------+---------+--------------+
| pasien_id | poli_id | puskesmas_id |
+-----------+---------+--------------+
| 1 | 1 | 1 |
| 5 | 2 | 2 |
| 1 | 1 | 3 |
| 9 | 3 | 4 |
| 1 | 3 | 5 |
| 5 | 2 | 1 |
| 1 | 1 | 3 |
| 8 | 1 | 2 |
| 10 | 3 | 6 |
| 5 | 2 | 5 |
+-----------+---------+--------------+
I want to show the total number (count) of visits to puskesmas table. then made field all_total
fter that I want to take patient visits where poli_id = 1 and used as a column bp. for other poly are the same as the
+----+----------------------+--------------+------+------+------+------+
| id | nama | All Total | BP | KIA | GIGI | JIWA |
+----+----------------------+--------------+------+------+------+------+
| 1 | BAMBANGLIPURO | 30 | 10 | 3 | 15 | 2 |
| 2 | BANGUNTAPAN | 35 | 20 | 4 | 11 | 0 |
| 3 | BANTUL | 15 | 10 | 0 | 5 | 0 |
| 4 | DLINGO | 12 | 10 | 1 | 1 | 0 |
| 5 | IMOGIRI | 10 | 5 | 2 | 1 | 2 |
| 6 | JETIS | 25 | 13 | 3 | 7 | 2 |
| 7 | KASIHAN | 20 | 10 | 10 | 0 | 0 |
| 8 | KRETEK | 23 | 20 | 1 | 1 | 1 |
| 9 | PAJANGAN | 10 | 5 | 1 | 3 | 1 |
| 10 | PANDAK | 0 | 0 | 0 | 0 | 0 |
+----+----------------------+--------------+------+------+------+------+
I've tried to make a query to display like this but it always fails to hold. Can anyone help to make such queries desired results
i have tried query like this :
select puskesmas_id,
sum(case when poli_id=1 then 1 else 0 end) bp,
sum(case when poli_id=5 then 0 else 1 end) gigi,
count(id) total
from loket
group by puskesmas_id
and result like this :
+--------------+------+------+-------+
| puskesmas_id | bp | gigi | total |
+--------------+------+------+-------+
| 1 | 97 | 126 | 143 |
| 6 | 74 | 185 | 210 |
| 8 | 131 | 179 | 190 |
| 7 | 90 | 92 | 98 |
| 2 | 33 | 39 | 54 |
| 4 | 158 | 248 | 263 |
| 3 | 66 | 68 | 72 |
+--------------+------+------+-------+
but puskesmas_id the value 0 does not perform data when querying

Concatenate and Count the multiple rows in single rows in mysql

I want to concatenate and count data of the same column, so I can concatenate but I can not count the repeated data.
Here's my table of data:
| ID | bills | class |
|-----|-------|-------|
| 1 | 0.5 | 2 |
| 2 | 1 | 1 |
| 3 | 0.5 | 2 |
| 5 | 1 | 3 |
| 6 | 0 | 2 |
| 7 | 0.5 | 1 |
| 8 | 1 | 2 |
| 9 | 1 | 3 |
| 10 | 0.5 | 1 |
| 11 | 0 | 2 |
| 12 | 1 | 1 |
| 13 | 0 | 3 |
| 14 | 1 | 2 |
| 15 | 0 | 1 |
| 16 | 0 | 1 |
| 17 | 0.5 | 3 |
| 18 | 0 | 3 |
| 13 | 0.5 | 3 |
Here's my sql query I'm using to concatenate data:
SELECT class AS lesson,
GROUP_CONCAT( bills ORDER BY bills ) AS bills
FROM tb_presence
GROUP BY class;
Here's my result below:
| class | bills |
|-------|------------------|
| 1 | 1,0.5,0.5,1,0,0 |
| 2 | 0.5,0,1,0,1 |
| 3 | 1,1,0,0.5,0,0.5 |
Now I would like to count the data that are equal, but continue with the same concatenation.
I want to "count" the data with the same values ​​and display concatenated (column observation and only to help understanding)
| class | bills | observation |
|-------|-------|-----------------------------|
| 1 | 2,2,2 | (2=0+0) (2=0.5+0.5) (2=1+1) |
| 2 | 2,1,2 | (2=0+0) (1=0.5) (2=1+1) |
| 3 | 2,2,2 | (2=0+0) (2=0.5+0.5) (2=1+1) |
Is this really possible?
Here is a solution (thanks to #wchiquito for the sqlfiddle) See http://sqlfiddle.com/#!2/2d2c8/1
As you can see it cannot dynamically determine the bills' values and count them. But there is a count per bill value that you want.
SELECT class AS lesson,
GROUP_CONCAT( bills ORDER BY bills ) AS bills
,SUM(IF(bills=0,1,0)) AS Count0
,SUM(IF(bills=0.5,1,0)) AS Count05
,SUM(IF(bills=1,1,0)) AS Count1
,COUNT(*) AS totalRecords
,COUNT(*)
- SUM(IF(bills=0,1,0))
- SUM(IF(bills=0.5,1,0))
- SUM(IF(bills=1,1,0))
AS Missing
FROM tb_presence GROUP BY class;
I added an extra record to show how the 'missing' column could show if you were not taking all values into consideration.
Results
| LESSON | BILLS | COUNT0 | COUNT05 | COUNT1 | TOTALRECORDS | MISSING |
|--------|-----------------------------------------|--------|---------|--------|--------------|---------|
| 1 | 0.00,0.00,0.50,0.50,1.00,1.00,1.00,4.00 | 2 | 2 | 3 | 8 | 1 |
| 2 | 0.00,0.00,0.50,0.50,1.00,1.00 | 2 | 2 | 2 | 6 | 0 |
| 3 | 0.00,0.00,0.50,0.50,1.00,1.00 | 2 | 2 | 2 | 6 | 0 |

Selecting Total value of items from 2 tables and update value of another TABLE (COMPLICATED QUERY)

My case is that I want to compute a player atk power to be used on a battle module that i made, but just wondering i have actually 2 options:
Calculate Damage Dealt from the server.(my CURRENT OPTIONS)
use PHP to calculate DAMAGE DEALT and UPDATE server DATABASE values.
pass 2 of the chara id and just calculate all in the QUERY and UPDATE all(is this possible).
Question: Can I do it in a query?(option B)
my current set-up:
1 character has 4 items and i compute the characters atk by adding all 4 of the item atk and the chara base atk in the client side. (which i think is prone to security holes)
and then update the values in the server side.
Here is my tables:
chara:
+----------+------------+----------------+-------------+------------+----------+----------+----------+-----------+-----------+
| chara_id | chara_name | chara_class_id | chara_level | chara_gold | chara_hp | chara_mp | chara_xp | chara_atk | chara_def |
+----------+------------+----------------+-------------+------------+----------+----------+----------+-----------+-----------+
| 1 | LawrenceX | 1 | 5 | 230 | -175 | 1000 | 0 | 7 | 3 |
| 3 | Viscocent | 2 | 2 | 96 | -206 | 1100 | 1700 | 5 | 5 |
| 4 | Piatos | 1 | 1 | 120 | -60 | 1000 | 0 | 7 | 3 |
| 5 | Hello | 1 | 1 | 300 | -50 | 1000 | 200 | 2 | 8 |
| 6 | Sample | 3 | 2 | 251 | -85 | 900 | 0 | 9 | 1 |
| 8 | Sampuro | 2 | 1 | 170 | 895 | 1100 | 700 | 5 | 5 |
| 12 | fail | 2 | 3 | 481 | 1100 | 1300 | 0 | 21 | 9 |
| 13 | new | 1 | 1 | 1000 | -80 | 1000 | 0 | 5 | 5 |
+----------+------------+----------------+-------------+------------+----------+----------+----------+-----------+-----------+
items:
+---------+-----------------+-----------+----------+----------+----------+---------------------------------+-------------------------------------------------+------------+
| 0 | None | 0 | 0 | 0 | 0 | pics/none.png | | 400 |
| 1 | Axe | 1 | 220 | 10 | 0 | pics/weapons/axe.png | Another lumberjack axe is another man's weapon. | 200 |
| 2 | Wooden Sword | 1 | 70 | 0 | 0 | pics/weapons/wooden-sword.png | A wooden sword, 99% made from wood | 225 |
| 3 | Dagger | 1 | 60 | 5 | 0 | pics/weapons/dagger.png | A Dagger, Cheap and Sharp | 55 |
| 4 | Bow | 1 | 120 | 1 | 0 | pics/weapons/bow.png | The basics and simplest of all bows. | 120 |
| 5 | Helmet | 4 | 0 | 50 | 0 | pics/headgears/helmet.png | iron helmet - made from an iron pot scraps. | 155 |
| 6 | Tunic | 2 | 10 | 10 | 0 | pics/armors/tunic.png | A peasants tunic. | 50 |
| 7 | Armour | 2 | 0 | 75 | 0 | pics/armors/armour.png | | 150 |
| 8 | Necklace | 3 | 25 | 15 | 0 | pics/accessories/necklace.png | | 199 |
| 9 | Studded Leather | 2 | 25 | 60 | 0 | pics/armors/studded-leather.png | | 240 |
+---------+-----------------+-----------+----------+----------+----------+---------------------------------+-------------------------------------------------+------------+
equipment:
+----------+----------+-----------+-------------+----------+---------+
| equip_id | chara_id | weapon_id | headgear_id | armor_id | ring_id |
+----------+----------+-----------+-------------+----------+---------+
| 3 | 1 | 14 | 5 | 6 | 8 |
| 5 | 3 | 4 | 5 | 6 | 8 |
| 6 | 4 | 11 | 5 | 7 | 8 |
| 7 | 5 | 12 | 5 | 6 | 8 |
| 8 | 6 | 3 | 16 | 7 | 8 |
| 10 | 8 | 15 | 5 | 7 | 8 |
| 13 | 12 | 14 | 5 | 6 | 17 |
| 40 | 13 | 3 | 5 | 7 | 8 |
+----------+----------+-----------+-------------+----------+---------+
table relationships:
1 chara = 1 equipment
1 weapon_id, armor_id, ring_id, headgear_id = 1 item (total of 4 items, headgear_id = 1 item).
I CAN GET THE EQUIPMENTS OF A CHARACTER BY USING THIS QUERY(KUDOS #JC):
SELECT i1.item_atk weapon_atk,i1.item_def weapon_def,
i2.item_atk headgear_atk,
i2.item_def headgear_def,
i3.item_atk armor_atk,
i3.item_def armor_def,
i4.item_atk ring_atk,
i4.item_def ring_def
FROM equipment e LEFT JOIN
item i1 ON e.weapon_id = i1.item_id LEFT JOIN
item i2 ON e.headgear_id = i2.item_id LEFT JOIN
item i3 ON e.armor_id = i3.item_id LEFT JOIN
item i4 ON e.ring_id = i4.item_id
WHERE e.chara_id = 1
RESULTS:
+------------+------------+--------------+--------------+-----------+-----------+----------+----------+
| weapon_atk | weapon_def | headgear_atk | headgear_def | armor_atk | armor_def | ring_atk | ring_def |
+------------+------------+--------------+--------------+-----------+-----------+----------+----------+
| 275 | 25 | 0 | 50 | 10 | 10 | 25 | 15 |
+------------+------------+--------------+--------------+-----------+-----------+----------+----------+
now i want to total the atk and def of that character equipment and return it in that query
expected results:
+------------+------------+
| total_atk | total_def |
+------------+------------+
| 310 | 100 |
+------------+------------+
this is the simplest way that I can think of.
SELECT IFNULL(W.item_atk, 0) + IFNULL(H.item_atk, 0) + IFNULL(A.item_atk, 0) + IFNULL(R.item_atk, 0) AS total_atk
, IFNULL(W.item_def, 0) + IFNULL(H.item_def, 0) + IFNULL(A.item_def, 0) + IFNULL(R.item_def, 0) AS total_def
FROM equipment E
LEFT JOIN item W ON W.item_id = E.weapon_id
LEFT JOIN item H ON H.item_id = E.headgear_id
LEFT JOIN item A ON A.item_id = E.armor_id
LEFT JOIN item R ON R.item_id = E.ring_id
WHERE E.chara_id = 1
I have renamed the aliases of tables to track them easily. And I used IFNULL in case the character has no particular equipment.
==================================================================================
Dude, I just made another query, I think this is faster than the one above. Though, I haven't tested them.
SELECT SUM(IFNULL(I.item_atk, 0)) AS total_atk
, SUM(IFNULL(I.item_def, 0)) AS total_def
FROM equipment E
LEFT JOIN item I ON I.item_id = E.weapon_id
OR I.item_id = E.headgear_id
OR I.item_id = E.armor_id
OR I.item_id = E.ring_id
WHERE E.chara_id = 1
GROUP BY E.chara_id

Categories