Why SUM() counts row twice and displaying double of actual result in here ?
Here I m trying to count total rows of status that has 0 value from the inv_id table of each student (inv_id.s_id) .
it has to show 4 based on the row number in inv_lst table but here it is showing 8.
If fee.id is GROUP_BY then it shows actual SUM but same student id starts to duplicate.
Please see fiddle - SQL Fiddle
Database Structure
class
id | ttl
===========
1 | One
2 | Two
section
id | ttl
===========
1 | A
2 | B
fee
id | ttl
===============
1 | Annual
2 | Monthly
student
id | ttl | cls | sec
===========================
1 | John| 1 | 1
2 | Paul| 1 | 1
3 | Rina| 2 | 1
sec_fee
id | c_id| s_id| f_id| fee
===================================
1 | 1 | 1 | 1 | 1000
2 | 2 | 1 | 2 | 560
inv_id
id | s_id| ft_id | status
==================================
1 | 1 | 1 | 0
2 | 1 | 2 | 0
3 | 1 | 3 | 0
4 | 1 | 4 | 0
Mysql
SELECT
student.id, student.ttl AS stdt,
cls.ttl AS cls,
sec.ttl AS sec,
GROUP_CONCAT(DISTINCT fee.id, '.', fee.ttl, '-', sec_fee.fee,'<br/>' ORDER BY sec_fee.f_id) AS amnt,
SUM(inv_id.status=0) AS upad,
SUM(inv_id.status=1) AS pad
FROM
student
JOIN
cls ON cls.id=student.cls
LEFT JOIN
sec ON sec.id=student.sec
LEFT JOIN
inv_id ON inv_id.s_id = student.id
LEFT JOIN
sec_fee ON sec_fee.c_id = student.cls
LEFT JOIN
fee ON fee.id = sec_fee.f_id
WHERE
cls.id = 1
Payment_Detail_Table
payment_detail_id| payment_id | payment_status | total | user_id | company_id
10001 | 10| 1 | 100 1 103
10002 | 11| 2 | 200 1 103
10003 | 12| 2 | 300 2 104
10004 | 13| 1 | 400 2 104
10005 | 14| 0 | 500 1 105
10006 | 15| 2 | 600 1 103
Payment_Table
payment_id| payment_type|
10 | 1 |
11 | 1 |
12 | 1 |
13 | 1 |
14 | 0 |
15 | 0 |
How to get the user_ids that have payment_type of 1 and payment_type of 0 from Payment_Table?
The purpose is to find that they have made two kind of payments and for those who have paid two of them, they must have payment_status of 2 , but if
for example, if the user_id is 1 and company_id is 103, the output must be 100+200+600=900.
This user with this company_id has the payment_Type 0 and 1 and for those two conditions (payment_type=1 and payment_type=0) have finished them successfully with payment_Status of 2 even though have a failed payment earlier
For example payment_detail_id is 1001 have payment_status of 1.
Is this what you are looking for ?
SELECT user_id, company_id
FROM (select payment_detail_table.user_id AS user_id,payment_detail_table.company_id AS company_id
from payment_detail_table
where (EXISTS(SELECT * FROM payment_table WHERE payment_table.payment_id=payment_detail_table.payment_id AND payment_table.payment_type=1)) AND payment_detail_table.payment_status = 2
group by concat(payment_detail_table.user_id,'-',payment_detail_table.company_id)) T1
INNER JOIN
(SELECT payment_detail_table.user_id AS user_id,payment_detail_table.company_id AS company_id
FROM (select payment_detail_table.user_id AS user_id,payment_detail_table.company_id AS company_id
from payment_detail_table
where (EXISTS(SELECT * FROM payment_table WHERE payment_table.payment_id=payment_detail_table.payment_id AND payment_table.payment_type=0)) AND payment_detail_table.payment_status = 2
group by concat(payment_detail_table.user_id,'-',payment_detail_table.company_id)) T2
USING (user_id, company_id)
SELECT
DISTINCT user_id
FROM
Payment_Detail_Table D
WHERE
EXISTS(
SELECT
*
FROM
Payment_Table P1
WHERE
P1.payment_id = D.payment_id
AND
P1.payment_type = 1
)
AND
EXISTS(
SELECT
*
FROM
Payment_Table P2
WHERE
P2.payment_id = D.payment_id
AND
P2.payment_type = 0
)
Hello, Im stuck with mysql subquery, this is the table I have
table detail_order
==============================
id_detail | id_order | id_toko
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 1 | 4
table ket_detail
==================================
id_ket | id_detail | id_size | qty
1 | 1 | 7 | 3
2 | 1 | 9 | 1
3 | 1 | 5 | 2
4 | 2 | 7 | 8
table size
=================================
id_size | size | id_color | stock
7 | 40 | 6 | 30
9 | 42 | 6 | 20
5 | 39 | 5 | 30
table color
==========================
id_color | color
6 | green
5 | red
Im trying in subquery to show qty on table ket_detail with where clause, but when Im try it subquery return more than one row.
this is my query
SELECT dt.id_detail,
SUM(tk.qty) AS tot_order,
COUNT(dm.color) AS tot_color,
(SELECT ket.qty FROM ket_detail AS ket, t_size AS u
WHERE u.id_size=ket.id_size AND u.size = 40) AS size_40
FROM detail_order AS dt
LEFT JOIN ket_detail AS tk ON tk.id_detail=dt.id_detail
LEFT JOIN t_size AS u ON u.id_size = tk.id_size
LEFT JOIN t_color AS dm ON dm.id_color=u.id_color
WHERE dt.id_order = 1
GROUP BY dt.id_detail
but when I change size to 39 the data like this
id_detail | tot_order | tot_color | size_40
============================================
1 | 6 | 2 | 2
2 | 8 | 1 | 2
3 | NULL | 0 | 2
4 | NULL | 0 | 2
what do I want is the data like this
id_detail | tot_order | tot_color | size_40
============================================
1 | 6 | 2 | 3
2 | 8 | 1 | 8
3 | NULL | 0 | NULL
4 | NULL | 0 | NULL
You don't need a subquery to get the size = 39 or size = 40 data. You can use conditional aggregation instead:
SELECT dt.id_detail,
SUM(tk.qty) AS tot_order,
COUNT(dm.color) AS tot_color,
SUM(CASE
WHEN u.size = 39 THEN tk.qty
ELSE 0
END) AS size_39,
SUM(CASE
WHEN u.size = 40 THEN tk.qty
ELSE 0
END) AS size_40
FROM detail_order AS dt
LEFT JOIN ket_detail AS tk ON tk.id_detail=dt.id_detail
LEFT JOIN t_size AS u ON u.id_size = tk.id_size
LEFT JOIN t_color AS dm ON dm.id_color=u.id_color
WHERE dt.id_order = 1
GROUP BY dt.id_detail;
Demo here
The proper way to do it with a subquery is:
SELECT dt.id_detail,
SUM(tk.qty) AS tot_order,
COUNT(dm.color) AS tot_color,
(SELECT SUM(ket.qty)
FROM ket_detail AS ket
JOIN t_size AS u ON u.id_size=ket.id_size
WHERE ket.id_detail = dt.id_detail AND u.size = 40) AS size_40
FROM detail_order AS dt
LEFT JOIN ket_detail AS tk ON tk.id_detail=dt.id_detail
LEFT JOIN t_size AS u ON u.id_size = tk.id_size
LEFT JOIN t_color AS dm ON dm.id_color=u.id_color
WHERE dt.id_order = 1
GROUP BY dt.id_detail;
Demo here
If you need to select the total quantity for more than one sizes, then you have to repeat the subquery for each required size. Hence, I think, the first query provides a solution that is cleaner, easier to extend and more efficient.
My mysql table is:
Id | value | count_of_past_lower_values
1 | 120 | 0
2 | 210 | 1
3 |150 | 1
4 |140 | 1
5 |200 | 3
Given id and values, I have to update 3rd col. I made a query using SUM(IF(value<X,1,0)) but not able to identify right expression for X.
Issuing a self-left-join with conditional sum would suffice:
select
a.id,
a.value,
sum(case when a.value > b.value then 1 else 0 end) as count_of_past_lower_values
from yourtable a
left join yourtable b on a.id > b.id
group by a.id, a.value
order by a.id
Result
id | value | count_of_past_lower_values
----+-------+----------------------------
1 | 120 | 0
2 | 210 | 1
3 | 150 | 1
4 | 140 | 1
5 | 200 | 3
I have a simple query where I select available x Rooms with x Adults + x Children per hotel that matches a date range, but I'm having a hard time trying to figure out how to query a list of rooms per hotel like this:
1 Room with 2 Adults / 0 Children
1 Room with 4 Adults / 2 Children
1 Room with 2 Adults / 1 Children
Here is my query:
SELECT COUNT(pl.day) AS Days,
p.property_ID AS Hotel_ID,
p.name AS Hotel_Name,
r.room_name AS Room_Name,
r.room_type_ID AS Room_ID
FROM property p
INNER JOIN room_type r ON p.property_ID=r.property_ID
AND (r.max_adults >= 3
AND r.max_children >= 0)
INNER JOIN plan pl ON pl.room_type_ID=r.room_type_ID
AND (pl.day >= "2014-07-07"
AND pl.day <= "2014-07-11")
GROUP BY Room_ID,
Hotel_ID HAVING Days = 4
EDIT
How do I add 'No_of_Room' in SELECT that differentiates the room_types by the room number, example result of a single room:
Array
(
[Room_Price] => 160.00
[Days] => 4
[Hotel_ID] => 1
[Hotel_Name] => Hotel Alfa
[Room_Name] => Room type C
[Room_ID] => 3
[Max_Adults] => 3
[Max_Children] => 1
[No_of_Room] => 1 // What number of room does this room_type belongs to
)
Then I can show the results like:
EDIT
Rooms table
Rooms(
ID,
hotel_id
room_name,
max_Adults,
max_Children
);
-- Populate
INSERT INTO Rooms VALUES (1,1,"Room A",2,1),(2,1,"Room B",2,5),(3,1,"Room C",3,0);
INSERT INTO Rooms VALUES (1,2,"Room A",2,1),(2,2,"Room B",2,5),(3,3,"Room C",3,4);
EXAMPLES OF USING VIEWS TO MAKE THINGS NICER.
For this project authors may have aliases, for example one book may have "S. Lang" as the author, another might have "Serge Lang", the primary author is the main form (Serge Lang) and the secondaries are things like "S. Lang".
It is important to relate these, ideally I'd like a table with "AuthorId" and "PrimaryAuthorId" as columns, that way I could just select PrimaryAuthorId from it on AuthorId being equal to something.
To do this the view is defined as:
select
`BookSystem_AuthorList`.`AuthorId` AS `AuthorId`,
if((`BookSystem_AuthorList`.`duplicateOf` = 0),
`BookSystem_AuthorList`.`AuthorId`,
`BookSystem_AuthorList`.`duplicateOf`
) AS `PrimaryAuthorId`
from `BookSystem_AuthorList`;
Then
SELECT PrimaryAuthorId FROM BookSystem_PrimaryAuthorId WHERE AuthorId=10;
gives:
7
Which is much nicer for joining!
I then use this view to define another view (EditionAuthorsWithPrimaryId) - this gets the authors of an edition - and the primary author (I can then join to get names as needed)
select
`BookSystem_EditionAuthors`.`BindingId` AS `BindingId`,
`BookSystem_EditionAuthors`.`EditionId` AS `EditionId`,
`BookSystem_EditionAuthors`.`AuthorId` AS `AuthorId`,
`BookSystem_EditionAuthors`.`Position` AS `Position`,
(select
`BookSystem_PrimaryAuthorId`.`PrimaryAuthorId`
from `BookSystem_PrimaryAuthorId`
where (`BookSystem_PrimaryAuthorId`.`AuthorId` = `BookSystem_EditionAuthors`.`AuthorId`)
) AS `PrimaryAuthorId`
from `BookSystem_EditionAuthors`;
Now I can do:
SELECT * FROM BookSystem_EditionAuthorsWithPrimary WHERE EditionId=10;
BindingId, EditionId, AuthorId, Position, PrimaryAuthorId
10, 10, 10, 0, 7
Much nicer!
this next query is a great example
select
`BookSystem_BookList`.`BookId` AS `Id`,
`BookSystem_BookList`.`Title` AS `Name`,
`BookSystem_BookList`.`UserId` AS `UserId`,
`BookSystem_BookList`.`BookType` AS `Subtype`,
1 AS `IsBook`,0 AS `IsSeries`,
0 AS `IsAuthor`
from `BookSystem_BookList`
union
select
`BookSystem_SeriesList`.`SeriesId` AS `Id`,
`BookSystem_SeriesList`.`SeriesName` AS `Name`,
`BookSystem_SeriesList`.`UserId` AS `UserId`,
'' AS `Subtype`,
0 AS `IsBook`,
1 AS `IsSeries`,
0 AS `IsAuthor`
from `BookSystem_SeriesList`
union
select
`BookSystem_AuthorList`.`AuthorId` AS `Id`,
concat(
`BookSystem_AuthorList`.`AuthorSurname`,', ',`BookSystem_AuthorList`.`AuthorForename`,
ifnull(
(select concat(
' (AKA: ',
group_concat(
concat(
`BookSystem_AuthorList`.`AuthorSurname`,
', ',
`BookSystem_AuthorList`.`AuthorForename`
) separator '; '
),')'
) AS `AKA` from `BookSystem_AuthorList`
where
(`BookSystem_AuthorList`.`duplicateOf` = `Id`)
group by (`BookSystem_AuthorList`.`duplicateOf` = `Id`)
),'')) AS `Name`,
`BookSystem_AuthorList`.`UserId` AS `UserId`,
'' AS `SubType`,
0 AS `IsBook`,
0 AS `IsSeries`,
1 AS `IsAuthor`
from `BookSystem_AuthorList`
where (`BookSystem_AuthorList`.`duplicateOf` = 0) order by `Name`;
IS HUGE!
But now I can get all the things for UserId=1 easily:
mysql> SELECT * FROM BookSystem_Index WHERE UserId = 1;
+----+----------------------------------------+--------+-------------+--------+----------+----------+
| Id | Name | UserId | Subtype | IsBook | IsSeries | IsAuthor |
+----+----------------------------------------+--------+-------------+--------+----------+----------+
| 4 | A First Course in Calculus | 1 | Normal | 1 | 0 | 0 |
| 2 | A First Course in Real Analysis | 1 | Normal | 1 | 0 | 0 |
| 2 | Algebra | 1 | | 0 | 1 | 0 |
| 13 | Analysis II assignments | 1 | Assignments | 1 | 0 | 0 |
| 14 | Author Test | 1 | Normal | 1 | 0 | 0 |
| 8 | b, g | 1 | | 0 | 0 | 1 |
| 7 | b, g (AKA: t, lll; Teal, lll) | 1 | | 0 | 0 | 1 |
| 1 | Calculus of Several Variables | 1 | Normal | 1 | 0 | 0 |
| 4 | DuBois, Paul | 1 | | 0 | 0 | 1 |
| 1 | Lang, Serge (AKA: Lang, S. E. R. G. E) | 1 | | 0 | 0 | 1 |
| 5 | Linear Algebra | 1 | Normal | 1 | 0 | 0 |
| 3 | Morrey, C. B. | 1 | | 0 | 0 | 1 |
| 6 | MySQL | 1 | Normal | 1 | 0 | 0 |
| 7 | Principles of Mathematical Analysis | 1 | Normal | 1 | 0 | 0 |
| 2 | Protter, M. H. | 1 | | 0 | 0 | 1 |
| 5 | Rudin, Walter | 1 | | 0 | 0 | 1 |
| 10 | t | 1 | Normal | 1 | 0 | 0 |
| 3 | Test | 1 | | 0 | 1 | 0 |
| 12 | Test 1 | 1 | Normal | 1 | 0 | 0 |
| 11 | Test 4.4.2014 | 1 | Normal | 1 | 0 | 0 |
| 8 | Topology and Analysis | 1 | Normal | 1 | 0 | 0 |
| 3 | Undergraduate Algebra | 1 | Normal | 1 | 0 | 0 |
| 1 | Undergraduate Texts in Mathematics | 1 | | 0 | 1 | 0 |
| 9 | w | 1 | Normal | 1 | 0 | 0 |
+----+----------------------------------------+--------+-------------+--------+----------+----------+
24 rows in set (0.00 sec)
The optimiser sees the view properly, it wont generate the full view, it effectively substitutes the required selects.
(Taken from a testing DB, not production, hence weird names like "TESTING")
First, the room type selection needs to be framed correctly. The following join would probably work.
EDIT:
The query has been edited to return only properties with all three room types. It has also been joined with the plan table.
SELECT
COUNT(pl.day) AS Days,
p.property_ID AS Hotel_ID,
p.name AS Hotel_Name,
r.room_name AS Room_Name,
r.room_type_ID AS Room_ID,
r.max_adults as Max_Adults,
r.max_children as Max_Children
FROM property p
INNER JOIN room_type r
ON p.property_ID=r.property_ID
INNER JOIN plan pl
ON pl.room_type_ID=r.room_type_ID
AND (pl.day >= '2014-07-07' AND pl.day <= '2014-07-11')
WHERE EXISTS
(SELECT 1
FROM room_type r1
WHERE p.property_ID=r1.property_ID
AND r1.max_adults = 2 AND r1.max_children = 0)
AND EXISTS
(SELECT 1
FROM room_type r2
WHERE p2.property_ID=r2.property_ID
AND r2.max_adults = 4 AND r2.max_children = 2)
AND EXISTS
(SELECT 1
FROM room_type r3
WHERE P.PROPERTY_ID=R3.PROPERTY_ID
AND r3.max_adults = 2 AND r3.max_children = 1)
GROUP BY
p.property_ID,
p.name,
r.room_name,
r.room_type_ID,
r.max_adults,
r.max_children
HAVING
COUNT(pl.day) = 4;