can someone tell me why he shows 16 entries when i already have 4?
http://sqlfiddle.com/#!9/0d2300/7
i want to show all results where the domain_id is 1 or something else.
What am I doing wrong?
I want to include all 3 tables that I get this record 4 times beacuse in my domain_check table are 4 records
I want:
id | domain_id | ssl_check | ssl_orgname
1 | 1 | 1 | SSL_TELEKOM
1 | 1 | 0 | SSL_TELEKOM
1 | 1 | 1 | SSL_MEDIA
1 | 1 | 1 | SSL_MEDIA
If you want the LAST row from domain_check and assuming the id identifies last row then add a condition to the where clause
SELECT domain.id,
domain_check.domain_id,
domain_check.ssl_check ,
ssl_info.domain_id,
ssl_info.ssl_organisation
FROM domain
INNER JOIN domain_check ON domain_check.domain_id = domain.id
INNER JOIN ssl_info ON domain_check.domain_id = ssl_info.domain_id
WHERE domain.id = 1 and
domain_check.id = (select max(id) from domain_check s1 where s1.domain_id = domain_check.domain_id);
+----+-----------+-----------+-----------+------------------+
| id | domain_id | ssl_check | domain_id | ssl_organisation |
+----+-----------+-----------+-----------+------------------+
| 1 | 1 | 1 | 1 | SSL_TELEKOM |
| 1 | 1 | 1 | 1 | SSL_TELEKOM |
| 1 | 1 | 1 | 1 | SSL_MEDIA |
| 1 | 1 | 1 | 1 | SSL_MEDIA |
+----+-----------+-----------+-----------+------------------+
4 rows in set (0.001 sec)
I think this would help you
SELECT
domain.id,
domain_check.domain_id,
domain_check.ssl_check,
ssl_info.domain_id,
ssl_info.ssl_organisation
FROM domain
LEFT JOIN domain_check ON domain_check.domain_id = domain.id
LEFT JOIN ssl_info ON domain_check.domain_id = ssl_info.domain_id
WHERE domain.id = 1 group by domain.id
Here is the screenshot https://prnt.sc/uljgzx
My 3 MYSQL tables are as follows:
Table 1: citizen
=============================
ID | Name | Sex | Address |
=============================
5 | James | Male | India
6 | Shella|Female | India
7 | Jan | Male | NY
8 | May | Female | USA
==============================
Table 2: benefits
==========================
ID| benefits
==========================
1 | SSS
2 | Coco Life
3 | PhiHealth
4 | Sunlife
==========================
Table 3: pensioners
============================
ID| benefits_ID | citizen_ID
============================
1 | 1 | 5
2 | 2 | 6
3 | 1 | 7
4 | 4 | 7
==========================
I want to display that looks like this:
====================================================================
Address | Total Citizen | Male | Female | SSS | Coco Life | Others |
====================================================================
India | 2 | 1 | 1 | 1 | 1 | 0 |
NY | 1 | 1 | 0 | 1 | 0 | 1 |
USA | 1 | 0 | 1 | 0 | 0 | 0 |
==================================================================
Anybody can give me a hint on how to do this?
You can do a Left Join from the Address table to the benefits table, via pensioners table, using the appropriate relationships. Left join will allows us to consider a Address even when there is no corresponding benefits entry for any of its citizens.
In order to count total citizens, male count and female count, you now need to use COUNT(DISTINCT ID) after the join. As Joining may create duplicate rows, as a citizen may have more than one benefits.
Also, in order to count "Other" benefits, we need to ensure that the benefit IS NOT NULL and it is NOT IN ('SSS', 'Coco Life').
In multi-table queries, it is advisable to use Aliasing for Code clarity (readability) and avoiding ambiguous behaviour.
SELECT
c.Address,
COUNT(DISTINCT CASE WHEN c.Sex = 'Male' THEN c.ID END) AS male_cnt,
COUNT(DISTINCT CASE WHEN c.Sex = 'Female' THEN c.ID END) AS female_cnt,
COUNT(DISTINCT c.ID) AS total_citizen_cnt,
COUNT(CASE WHEN b.benefits = 'SSS' THEN 1 END) AS SSS_cnt,
COUNT(CASE WHEN b.benefits = 'Coco Life' THEN 1 END) AS Coco_Life_cnt,
COUNT(CASE WHEN b.benefits IS NOT NULL AND
b.benefits NOT IN ('SSS', 'Coco Life') THEN 1 END) AS Others_cnt
FROM citizen AS c
LEFT JOIN pensioners AS p
ON p.citizen_ID = c.ID
LEFT JOIN benefits AS b
ON b.ID = p.benefits_ID
GROUP BY c.Address
I have the following 2 MySQL tables:
players:
| id | name |
|----|---------|
| 1 | Player1 |
| 2 | Player2 |
| 3 | Player3 |
scores:
| key | id | round | score |
|-----|----|-------|-------|
| 1 | 1 | Rd1 | 20 |
| 2 | 1 | Rd2 | 22 |
| 3 | 1 | Rd3 | 19 |
| 4 | 2 | Rd1 | 18 |
| 5 | 2 | Rd2 | 23 |
| 6 | 2 | Rd3 | 19 |
where scores.id=players.id
I will have upwards of 90 players in my 'players' table, what's the best way to query this and insert it into an HTML table to make it easier to view? I'm hoping to have an output similar to this:
| Player | Round 1 | Round 2 | Round 3 |
|---------|---------|---------|---------|
| Player1 | 20 | 22 | 19 |
| Player2 | 18 | 23 | 19 |
This is my first attempt at normalizing data in tables. Am I going to have to do number of cases? I'm not sure what the best way to pivot the data is with an INNER JOIN.
This is my solution, hope it helps :
SELECT
name as Player,
SUM(CASE WHEN (s.round='Rd1') THEN s.score ELSE 0 END) AS Round1,
SUM(CASE WHEN (s.round='Rd2') THEN s.score ELSE 0 END) AS Round2,
SUM(CASE WHEN (s.round='Rd3') THEN s.score ELSE 0 END) AS Round3
FROM
players p
JOIN scores s
on s.id=p.id
GROUP BY
name
This will output :
| Player | Round1 | Round2 | Round3 |
|---------|---------|---------|---------|
| Player1 | 20 | 22 | 19 |
| Player2 | 18 | 23 | 19 |
This Fiddle for you to test!
I have a sligthly alternative solution which uses subqueries with the following benefit that players with no no score gets listed too!!
SELECT
p.name,
ifnull((select score from scores where id = p.id and round='Rd1' limit 1), 0) as Round1,
ifnull((select score from scores where id = p.id and round='Rd2' limit 1), 0) as Round2,
ifnull((select score from scores where id = p.id and round='Rd3' limit 1), 0) as Round3
FROM players p
GROUP BY p.name, p.id
My previous problem and solution:
Get max and min from fields
This working OK, but i would like skip 0 and NULL in this examples.
For example:
First:
id | title
1 | aaa
2 | bbb
3 | ccc
Second:
id | first_id | one | two | three | four
1 | 1 | 3 | 0 | 4 | 6
2 | 2 | 4 | 4 | 1 | 2
3 | 3 | 1 | NULL | 3 | 4
this should show me:
id | title | min | max
1 | aaa | 3 | 6
2 | bbb | 1 | 4
3 | ccc | 1 | 4
and not:
id | title | min | max
1 | aaa | 0 | 6
2 | bbb | 1 | 4
3 | ccc | 0 | 4
In which example from my previous question is the best way to implement skip 0 and NULL?
Pop these into your clause
SELECT
f.id,
f.title
MIN(LEAST(greatest(coalesce(s.one,0),1), greatest(coalesce(s.two,0),1), greatest(coalesce(s.three,0),1), greatest(coalesce(s.four,0),1))) as min,
MAX(GREATEST(greatest(coalesce(s.one,0),1), greatest(coalesce(s.two,0),1), greatest(coalesce(s.three,0),1), greatest(coalesce(s.four,0),1))) as max
FROM
First f
INNER JOIN Second s
on f.id = s.first_id
GROUP BY
f.id,
f.title
You can use coalesce(fieldName, 1) to turn a null into a 1.
Again, as said in your previous question, this is HORRIBLE use of a query to force an answer. You should be changing the layout of the database.
Edit: I have nutted out the data you want, but before you look at it, be aware that if one of my colleagues wrote a script like this, he would be sacked on the spot. This is HIDEOUS and should NOT BE USED.
select
f.id,
f.title,
(select min(z.myVal) from
(
select
b.id,
b.first_id,
b.one as myVal
from
second b
where
b.one is not null
and b.one > 0
union
select
b.id,
b.first_id,
b.two as myVal
from
second b
where
b.two is not null
and b.two > 0
union
select
b.id,
b.first_id,
b.three as myVal
from
second b
where
b.three is not null
and b.three > 0
union
select
b.id,
b.first_id,
b.four as myVal
from
second b
where
b.four is not null
and b.four > 0
) z
where
f.id=z.first_id) as miniVal,
greatest(
coalesce(s.one,0),
coalesce(s.two,0),
coalesce(s.three,0),
coalesce(s.four,0)
) as maxiVal
from
first f,
second s
where
f.id=s.first_id
output Data
+------+-------+---------+---------+
| id | title | miniVal | maxiVal |
+------+-------+---------+---------+
| 1 | aaaa | 3 | 6 |
| 2 | bbbb | 1 | 4 |
| 3 | cccc | 1 | 4 |
+------+-------+---------+---------+
3 rows in set (0.00 sec)
Running this query made me throw up a little in my mouth. That's how wrong it is to write SQL like this.
While seemingly clunky, this solution should work:
SELECT
a.id, a.title, MIN(b.num) AS min, MAX(b.num) AS max
FROM
first a
LEFT JOIN
(
SELECT first_id, one AS num FROM second UNION ALL
SELECT first_id, two FROM second UNION ALL
SELECT first_id, three FROM second UNION ALL
SELECT first_id, four FROM second
) b ON
a.id = b.first_id AND
b.num IS NOT NULL AND
b.num > 0
GROUP BY
a.id, a.title
What this does is it actually gets each number column into its own row, but only the numbers that are not null and > 0. Before the GROUP BY, the result of the LEFT JOIN would look something like:
id | title | num
---------------------
1 | aaa | 3
1 | aaa | 4
1 | aaa | 6
2 | bbb | 1
2 | bbb | 2
2 | bbb | 4
2 | bbb | 4
3 | ccc | 1
3 | ccc | 3
3 | ccc | 4
Then by the groupings of each first (GROUP BY a.id, a.title), we can use the MIN() and MAX() aggregate functions on the num column to extract minimum and maximum values per first group:
id | title | min | max
----------------------------
1 | aaa | 3 | 6
2 | bbb | 1 | 4
3 | ccc | 1 | 4
In the case that a first_id had all four columns having NULL's or 0's, the min and max values would show up as NULL due to using a LEFT JOIN instead of an INNER JOIN as I believe this is would be a better behavior for your situation:
id | title | min | max
----------------------------
4 | ddd | NULL | NULL
USE:
WHERE COLUMN IS NOT NULL AND COLUMN <> 0;
I think you just need to nest the LEAST expressions:
LEAST(
NULLIF(one,0),
LEAST(
NULLIF(two,0),
LEAST(
NULLIF(three,0),
LEAST(
NULLIF(four,0),
null ))))
Edit I just looked it up. The LEAST function takes multiple arguments:
LEAST( NULLIF(one,0), NULLIF(two,0), NULLIF(three,0), NULLIF(four,0))
Edit 2 I see you want both min and max. Obviously you'd just change LEAST to GREATEST or MIN to MAX as needed.
This may be more straightforward or you may not have a handy least function.
SELECT
f.id, f.title,
(
SELECT MIN(NULLIF(val, 0))
FROM
(
SELECT one AS val UNION ALL
SELECT two UNION ALL
SELECT three UNION ALL
SELECT four
) AS vals
)
) as minval
FROM First f INNER JOIN Second s on f.id = s.first_id
You haven't specified if it's possible for all four columns to be null/0. We may need to tweak for that case.
You can use IFNULL():
WHERE IFNULL(fieldname, 0) != 0
ok, first of all sorry for the title, but I could not work out a better one :(
This is the problem:
I have two tables, properties and properties_rooms, linked each other by the propery ID.
properties table:
+---------------+------------+
| id_properties | pr_title |
+---------------+------------+
| 1 | test |
| 2 | dummy |
+---------------+------------+
properties_rooms table:
+---------------+-------------------+--------------+----------+
| id_prop_rooms | pro_id_properties | pro_id_rooms | pro_size |
+---------------+-------------------+--------------+----------+
| 1 | 1 | 4 | 5.00 |
| 2 | 1 | 18 | 17.00 |
| 3 | 2 | 6 | 12.00 |
| 4 | 2 | 24 | 11.00 |
| 5 | 1 | 4 | 10.00 |
| 6 | 1 | 6 | 10.00 |
| 7 | 1 | 6 | 12.00 |
+---------------+-------------------+--------------+----------+
I'm working on an advanced search, where users can search for a property that has more than a rooms of the same type (ie two bedrooms, 3 bathrooms and so on).
Sadly, I find myself stuck on this, since I can't "filter" the same dataset with multiple clause; if i have to filter only one there will be no problems, since I can use an HAVING clause.
I worked out this select:
SELECT id_properties, pro_id_rooms, COUNT(*) as total,
IF ((pro_id_rooms = 4 AND COUNT(*) >= 2) OR (pro_id_rooms = 6 AND COUNT(*) >= 2), 1, 0) as flag
FROM `properties`
INNER JOIN properties_rooms ON id_properties = pro_id_properties
WHERE id_properties IN (4,10)
GROUP BY id_properties, pro_id_rooms
ORDER BY id_properties
Inside the IN clause there are the properties that I know they have at least one of requested rooms. They came from a previous query since I have to work with GROUP BY and HAVING.
The IF part inside the select is built at run-time, since I get the information from the request.
This is the result:
+---------------+--------------+-------+------+
| id_properties | pro_id_rooms | total | flag |
+---------------+--------------+-------+------+
| 1 | 4 | 2 | 1 |
| 1 | 6 | 2 | 1 |
| 1 | 18 | 1 | 0 |
| 2 | 6 | 1 | 0 |
| 2 | 24 | 1 | 0 |
+---------------+--------------+-------+------+
I think it could work, I only need to add an HAVING flag > 0 and I'm done.
My question is, is there anything better?
Tables aren't very large: properties one could be something like 1k, rooms one about 10k.
I'm afraid that if the user puts too much rooms, the query would become an enormous IF statement...
SELECT id_properties, SUM(pro_id_rooms = 4) AS bedrooms, SUM(pro_id_rooms = 6) AS bathrooms
FROM `properties`
INNER JOIN properties_rooms ON id_properties = pro_id_properties
WHERE id_properties IN (4,10)
GROUP BY id_properties
HAVING bedrooms >= 3 AND bathrooms >= 2
Changes
SUM(pro_id_rooms = 4) AS bedrooms, SUM(pro_id_rooms = 6) AS bathrooms
For each checkbox the user has selected, you need a SUM(pro_id_rooms = x) AS nrofx in your WHERE.
HAVING bedrooms >= 3 AND bathrooms >= 2
This is where you check the number of a particular room.