I got stuck in a scenario where I need to add columns from two rows after using GROUP BY.
My query goes as:
select AcctId,DC,sum(TrnAmt) from TableId
group by AcctId,DC
order by AcctId,DC
Result:-
VcrAcctId DrCr SumTranAmt
51 C 37469
51 D 37000
My expected result is:
VcrAcctId Actual
51 37469-37000
How can I get my expected result in the same query?
Based on discussion in the comments I think you need
SELECT AcctId,
Sum(CASE DC
WHEN 'C' THEN TrnAmt
WHEN 'D' THEN -TrnAmt
ELSE 0
END) AS DC
FROM TableId
GROUP BY AcctId
ORDER BY AcctId
If in fact you do want the credits and debits split out you can use
SELECT AcctId,
Sum(CASE
WHEN DC = 'C' THEN TrnAmt
ELSE 0
END) AS C,
Sum(CASE
WHEN DC = 'D' THEN TrnAmt
ELSE 0
END) AS D
FROM TableId
GROUP BY AcctId
ORDER BY AcctId
You could cast the SUM expressions to varchar and concatenate them to get the results shown in the question if that is what is actually needed.
This is assuming Actual is ordered on DrCR, so that C result row comes before D result row.
Also, replace Table1 with a CTE from your original query, so that you first sum up per VcrAcctId and DC.
SELECT VcrAcctId, STUFF((SELECT '-' + convert(varchar(100),SumTranAmt)
FROM Table1 I
WHERE Table1.VcrAcctId = I.VcrAcctID
ORDER BY DrCr
FOR XML PATH ('')),1,1,'')
FROM Table1
Group by VcrAcctId
SQL Fiddle Demo
Related
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 made query like this:
SELECT DISTINCT TahunMasuk (SELECT COUNT(LamaStudi)
FROM studi WHERE LamaStudi < 2) from studi order by TahunMasuk
but, the query is error. What may I do to solve that query so that I can count LamaStudi based by TahunMasuk? The result example is like this
Here is my table
studi
Thanks in advance
This query should return the result you want:
SELECT TahunMasuk,
COUNT(CASE WHEN LamaStudi < 2 THEN 1 END) AS `LamaStudi < 2`,
COUNT(CASE WHEN LamaStudi BETWEEN 2 AND 2.4 THEN 1 END) AS `LamaStudi < 2-2.4`,
COUNT(CASE WHEN LamaStudi > 2.4 THEN 1 END) AS `LamaStudi > 2.4`,
FROM studi
GROUP BY TahunMasuk;
In your sample data, you have some rows where LamaStudi is NULL, but it's not clear how you want to handle that. If you want NULL to be counted as zero, then you need this small modification:
COUNT(CASE WHEN COALESCE(LamaStudi,0) < 2 THEN 1 END) AS `LamaStudi < 2`,
You were using DISTINCT incorrectly. The DISTINCT option applies to all columns in the select-list.
The following rows are all distinct rows:
a b c
a b d
a e d
DISTINCT keeps a row in the result if any column is different from other rows.
If you want to reduce the result set to rows with distinct values in one column, use GROUP BY.
You can use GROUP BY:
SELECT TahunMasuk, COUNT(*)
FROM studi
GROUP BY TahunMasuk
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.
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