I am not able to make a query to get some crossed values. My knowledge of mysql is not so good to make this kind of things.
I have two tables, signedup and signedupLocal. Both with same fields: name, surname1, surname2, NIF, year,city, status and dateSigned.
I want to get all values from both tables together when the status is 0 in both ordered by surname1 and surname2 (A to Z). ALso I want to have a new field called for example "app" in which it says yes or no depending on which table the data came. If signedpupLocal, yes else no.
After that, I want to do the same thing when status is 1 ordered by dateSigned (older first).
I haven't tried to go so far to test a complete query because I have problems with just part of it.
I already tried something like:
SELECT signedupLocal.name,
signedupLocal.surname1,
signedupLocal.surname2,
signedupLocal.NIF,
signedupLocal.year,
signedupLocal.city,
signedup.name,
signedup.surname1,
signedup.surname2,
signedup.NIF,
signedup.year,
signedup.city
FROM signedup, signedupLocal
WHERE signedup.id_Event = 78
AND signedupLocal.id_Event = 78
AND signedupLocal.status = 0
AND signedup.status = 0
But it fails.
SELECT name, surname1, surname2, NIF, year, city, status, 'no' as app,
case when status = 1 then datesigned else '2099-12-31' end as datesigned_sort,
case when status = 0 then surname1 else '' end as surname1_sort,
case when status = 0 then surname2 else '' end as surname2_sort
FROM signedup
WHERE id_Event = 78 AND status in(0,1)
UNION ALL
SELECT name, surname1, surname2, NIF, year, city, status, 'yes' as app,
case when status = 1 then datesigned else '2099-12-31' end as datesigned_sort,
case when status = 0 then surname1 else '' end as surname1_sort,
case when status = 0 then surname2 else '' end as surname2_sort
FROM signedupLocal
WHERE id_Event = 78 AND status in(0,1)
ORDER BY 7 asc, 9 desc, 10 asc, 11 asc
Note that when using UNION, you need to use column numbers, not column names in the ORDER BY. And I used UNION ALL as it is more efficient than UNION, as the latter remove duplicates - which causes effort for the database engine. So if you know there are none, you can avoid this.
For the sorting, I use a constant for the cases where the record should not be sorted by a sort column.
Use a UNION of 2 queries to concatenate the results.
SELECT * FROM (
SELECT *, "signedup" AS tablename FROM signedup WHERE …
UNION
SELECT *, "signedupLocal" AS tablename FROM signedupLocal WHERE …
) U
ORDER BY U.dateSigned DESC
Related
In Mysql I have the following table - property_alert_status having columns :
id (primary), propertyId, status, updatedAt
All record - select * from property_alert_status
id
propertyId
status
updatedAt
1
1
ALERT
1658304031
2
2
OK
1658300273
3
3
ALERT
1658312336
4
3
ALERT
1658313979
5
3
OK
1658312336
6
2
OK
1658312336
From the above table, I want to fetch the most recent record for the property based on status. If Status is 'ALERT' then most recent 'ALERT' record otherwise Most recent 'OK' record.
Ex - For propertyId '3' there are three records but most recent alert status is of id 4 so the output for the above propertyId 3 should be:
id
propertyId
status
updatedAt
4
3
ALERT
1658313979
Expected Output should be:
id
propertyId
status
updatedAt
1
1
ALERT
1658304031
4
3
ALERT
1658313979
6
2
OK
1658312336
I have made one query but the output is not as expected:
Select mainStatus.* from (
SELECT *
FROM property_alert_status
ORDER BY
(CASE
WHEN status = "ALERT" THEN 0
ELSE 1
END) ASC, updatedAt DESC
) mainStatus group by propertyId;
Innerquery is giving the right result but when selecting only a single record by grouping propertyId, giving the wrong result.
Inner query giving result:
id
propertyId
status
updatedAt
4
3
ALERT
1658313979
3
3
ALERT
1658312336
1
1
ALERT
1658304031
5
3
OK
1658312336
6
2
OK
1658312336
2
2
OK
1658300273
The final query gives result:
id
propertyId
status
updatedAt
1
1
ALERT
1658304031
2
2
OK
1658300273
3
3
ALERT
1658312236
Note: Using Mysql v5.6.50.
Tables in SQL are unordered data set. A query result is a table. So the ORDER BY clause in your subquery doesn't have to sort the rows. Don't rely on it. Some DBMS even raise an error when you have an ORDER BY at the end of a subquery.
Moreover, select * from ... group by ... is invalid. If you group by a column, you can select that column plus aggregates, i.e. sums, maximums, averages and so on. You cannot select other original column values (except for the case they are functionally dependent on your group, such as a person's name when you group by the person's ID). MySQL should raise an error, and if it doesn't, this probably means that you are working in a cheat mode that MySQL invented in their early days. Make sure to always SET sql_mode = 'ONLY_FULL_GROUP_BY'; when working with MySQL in order to have the DBMS help you with invalid aggregation queries.
As to the task: You can rank your rows with ROW_NUMBER.
SELECT *
FROM
(
SELECT
s.*,
ROW_NUMBER() OVER (PARTITION BY propertyid ORDER BY status, updatedat DESC) AS rn
FROM vk_property_temperature_alert_status s
WHERE temperature_status IN ('ALERT', 'OK')
) ranked
WHERE rn = 1;
For old MySQL versions I see two approaches. Either select only those rows for which not exists a better row or select those rows that are the best for their group. The second approach seems easier. It's basically writing a subquery that determines the top row for the property ID, so you can check whether the row you are looking at is a top row.
SELECT *
FROM vk_property_temperature_alert_status s
WHERE id =
(
SELECT s2.id
FROM vk_property_temperature_alert_status s2
WHERE s2.temperature_status IN ('ALERT', 'OK')
AND s2.propertyid = s.propertyid
ORDER BY s2.status, s2.updatedat DESC
LIMIT 1
);
I don't know if this will work, wrote just for fun as the question was very interesting:
SELECT
MAX(maxId),
propertyId,
`status`,
MAX(dates) updatedAt
FROM
(
SELECT
firstResult.*,
(CASE WHEN #running_propertyId=0 THEN #running_propertyId:=propertyId ELSE #running_propertyId:=#running_propertyId END) runningPro,
(CASE WHEN #running_status='' THEN #running_status:=`status` ELSE #running_status:=#running_status END) runningStat,
(CASE WHEN #running_variable >0 AND #running_propertyId =propertyId THEN #running_variable:=#running_variable+1 ELSE #running_variable:=1 END )var,
(CASE WHEN #running_variable =1 THEN #running_date:=updatedAt ELSE (CASE WHEN `status`='ALERT' THEN #running_date:=updatedAt ELSE
( CASE WHEN #running_status=`status` THEN #running_date:=updatedAt ELSE #running_date:=#running_date END) END) END )dates,
(CASE WHEN #running_variable =1 THEN #running_id:=id ELSE (CASE WHEN `status`='ALERT' THEN #running_id:=id ELSE
( CASE WHEN #running_status=`status` THEN #running_id:=id ELSE #running_id:=#running_id END) END) END )maxId,
#running_propertyId:=propertyId,
#running_status:=`status`
FROM (SELECT
a.*,
#running_propertyId:=0,
#running_status:='',
#running_variable:=0,
#running_date:=0,
#running_id:=0
FROM
property_alert_status a
ORDER BY
`propertyId`
,`updatedAt`) firstResult
) final
GROUP BY propertyId
By combining my query with some changes into the #Thorsten Kettner's query -
Following Query giving expected result:
SELECT
*
FROM
property_alert_status s
WHERE
id = (SELECT
s2.id
FROM
property_alert_status s2
WHERE
s2.propertyId = s.propertyId
ORDER BY (CASE
WHEN s2.status = 'ALERT' THEN 0
ELSE 1
END) ASC, s2.updatedAt DESC
LIMIT 1);
I need a help with following problem:
So I have a table TABLE1 with columns Date, Name, STAT1, STAT2, PROBLEM1
I have a query like this:
SELECT Date, Name, sum(STAT1), sum(STAT2)
FROM TABLE1
WHERE PROBLEM1 <> 0
GROUP BY Date, Name
The result of this query is what I want but I also need to add 2 columns: TOTALCOUNT which is basically the number of rows for each group without applying the filter (PROBLEM1 <> 0 ) and COUNTERRORS which is count for each group where PROBLEM1 = 0.
So to give you further example. For a Date A, and Name B I have 1000 rows. 300 of them have PROBLEM1 = 0.
I run the first query I mentioned above and it calculates my sum(STAT1), sum(STAT2) based on 700 rows because of the filter WHERE PROBLEM1 <> 0. And I need to find a way to add two columns to the result so in the end my table would look like:
DATE NAME sum(STAT1) sum(STAT2) TOTALCOUNT COUNTERRORS
A B 50 3.5 1000 300
Is it possible to do? I was trying using subqueries but without a success.
You can do conditional aggregation :
SELECT Date, Name,
sum(case when PROBLEM1 <> 0 then stat1 else 0 end) as stat1,
sum(case when PROBLEM1 <> 0 then stat2 else 0 end) as stat2,
count(*) as TOTALCOUNT,
sum(PROBLEM1 = 0) as COUNTERRORS
FROM TABLE1
GROUP BY Date, Name;
I have a table with a date column and a column named TDBUY (which can be 0 or 1). Now I do following:
SELECT tradedate,aktienstat.TDBuyPerfection,count(*) as cc from
aktienstat group by TradeDate,TDBuyPerfection HAVING cc >= '0' ORDER
BY TradeDate desc limit 100;
And get:
I don`t want to display f.e. the 2018-02-08 or 2018-02-07 with 0 count (line 1 and line 3) because there are 1 count with 1 each. But if no TDBUY then the date should be displayed with 0 count.
Can anyone here tell me please how to do it?
THANKS
Edit: It works also fine with SUM instead of Count.
SELECT tradedate,aktienstat.TDBuyPerfection,sum(aktienstat.TDBuyPerfection) as summe from
aktienstat group by TradeDate ORDER
BY TradeDate desc limit 100;´
We can try doing this via a pivot query:
SELECT
tradedate,
CASE WHEN cnt_1 = 0 THEN 0 ELSE 1 END AS TDBuyPerfection,
CASE WHEN cnt_1 = 0 THEN cnt_0 ELSE cnt_1 END AS cnt
FROM
(
SELECT
tradedate,
COUNT(CASE WHEN TDBuyPerfection = 0 THEN 1 END) AS cnt_0,
COUNT(CASE WHEN TDBuyPerfection = 1 THEN 1 END) AS cnt_1
FROM aktienstat
GROUP BY tradedate
) t;
The pivot trick works here because it brings the zero and one counts into a single record. There, it is relatively easy to test both counts. In your current form, it is much harder to check the counts.
The demo below shows that zero buy dates appear with only the zero count, while dates having a buy count show only the buy data.
Demo
This is my first post, so any general corrections to format/content are also welcome. I'm relatively new to SQL.
Say I have a database which collects test results from an classification evaluation. I know what the expected outcome is for each test. I also have a column indicating whether the test was successful, ie the expected value returned matched the expected value. It looks something like this:
Expected_Result Result Success
A A True
A B False
B B True
A A True
B A False
I know I can return the total occurrences of each expected type withSELECT Expected_Result, COUNT(Expected_Result) FROM Evaluation_Results GROUP BY Expected_Result.
I know how to count the number of false detections for a specific expected outcome with SELECT COUNT(*) FROM Evaluation_Results WHERE Success = 'True' AND Expected_Result = 'A'
Where I'm struggling is combining the two. I would like the query to return a list of all distinct expected results, the total of each, the count of successful results, and the percentage of the total, like so:
Expected_Result Total Num_Successful Success_Rate
A 3 2 66.67
B 2 1 50.00
You could use a CASE expression to perform a condition check during aggregation. A case statement identifies a conditional outcome. For instance you could use:
select evaluation_result
, count(*) AS total
, sum(case when success='true' and result='a' then 1 else 0 end) AS num_successful
, sum(case when success='true' and result='a' then 1 else 0 end)/count(*) AS success_rate
from evaluation_results group by evaluation_result;
Basically what's happening there is you're taking a count(*) of all grades, a sum() of a 1 or 0 based on a conditional outcome, then performing the ratio math. There's no need for a join here. The CASE Expression is a powerful conditional statement which can be used in so many diverse ways.
Or for a more flexible solution have a look at this:
select evaluation_result
, count(*) AS total
, sum(case when success='true' and result=evaluation_result then 1 else 0 end) AS num_successful
, sum(case when success='true' and result=evaluation_result then 1 else 0 end)/count(*) AS success_rate
from evaluation_results group by evaluation_result;
You can use self join if table is same like.
SELECT distinct e.Expected_Result, COUNT(Expected_Result), sum(e1.columns name), avg(e1.column name)
FROM Evaluation_Results e
left join Evaluation_Results e1 on e1.col=e.col
GROUP BY e.Expected_Result
Use this simple Query and check for the result..
select Expected_Result, count(Expected_Result) Total,
sum(IF ('True' = Success, 1, 0) ) Num_Successful,
avg(IF ('True' = Success, 1, 0 )) Success_Rate
from Evaluation_Results group by Expected_Result
I have a temp table that I'm reading from, and I want to look at one of the columns that only has two grade values - either a 3 or a 4 and build two new columns - one that holds the count of the 3's and the other to hold the count of the 4's - by a particular grouping. My code looks like this.
Select Max(Counting) as Total
, student
, stdType
, Score3 = (SELECT count(*) from #tempBWMSHonors3 where score = '3')
, Score4 = (SELECT count(*) from #tempBWMSHonors3 where score = '4')
from #tempBWMSHonors3
group by student, stateID, grade, stdType
I also embedded an image that show an example of my temp table and what I'm trying to achieve (as well as the result I am getting - but don't want).
[]
I think you just want conditional aggregation, not subqueries:
select Max(Counting) as Total, student, stdType,
sum(case when score = '3' then 1 else 0 end) as Score3,
sum(case when score = '4' then 1 else 0 end) as Score4
from #tempBWMSHonors3
group by student, stdType;
Note: if score is a number and not a string, then you should not use single quotes for the constant.