How to use SELECT DISTINCT properly? - mysql

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

Related

want to get all dates but when there is one or more TDBUY = 1 then this date#TDBUY=0 not

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

MySQL count with a range condition

I have a query like this
select newscategory.CategoryName, count(distinct newsmain.id)
from newsmain join newscategory on
newscategory.CategoryName = newsmain.Category
group by CategoryName
and it is returning a correct results, like this:
CategoryName count(distinct newsmain.id)
Acupunctura 1
Neurologie 1
Test Category 2
"newsmain" table has an "AppPublished" datetime field and what I'm trying to do is to add a condition to the count which will do the counting based on if that "AppPublished" is in the range of two datetime variables. For an example, I would need a result like this:
CategoryName count(distinct newsmain.id)
Acupunctura 0
Neurologie 0
Test Category 1
Do I need to make a subquery or is there a way to add some condition to this query?
Because any added conditions in this query are resulting in unwanted filtering of the "CategoryName" column.
You can use a CASE condition like
select newscategory.CategoryName,
count(CASE WHEN AppPublished BETWEEN date1 and date2 THEN distinct newsmain.id END)
from newsmain join newscategory on
newscategory.CategoryName = newsmain.Category
group by CategoryName
(OR) like this
select newscategory.CategoryName,
sum(CASE WHEN AppPublished BETWEEN date1 and date2 THEN 1 ELSE 0 END)
from newsmain join newscategory on
newscategory.CategoryName = newsmain.Category
group by CategoryName

Adding columns resulting from GROUP BY clause

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

select case when not working as expected

I'm trying to understand how this works but can't figure it out yet.
I have made this simple uery to test the case-when-then-end clause...
SELECT case when quantity > 3
then count(*) end the_count_a,
case when quantity <= 3
then count(*) end the_count_b
FROM STOCK
my stock table has 30 items with different quantities, only 10 items have quantity over 3 but this is always returning 30.... WHY?
I think it should be returning two columns with values: 10 and 20
Any help will be appreciated!
Thx,
Leo
The value of count(*) means the count of all records (in the current group), regardless of where it is placed. If you want to count records that match a condition, you need to invert your case statement:
select count(case when quantity > 3 then 1 end) the_count_a,
count(case when quantity <= 3 then 1 end) the_count_b
from stock
SELECT
count(case when quantity > 3 then 1 else null end) end the_count_a,
count(case when quantity <= 3 then 1 else null end) end the_count_b
FROM STOCK
The aggregate function COUNT() in absense of a GROUP BY will return all rows in the table which have not been filtered by a WHERE clause. In your case, what you actually need are two subselects or a UNION, depending if you want columns or rows back:
/* Return columns with subselects */
SELECT
(SELECT COUNT(*) FROM STOCK WHERE quantity > 3) AS the_count_a
(SELECT COUNT(*) FROM STOCK WHERE quantity <= 3) AS the_count_b
MySQL is lenient about the presence of a FROM clause, so it can be omitted from the outer query.
/* Return rows instead of columns with UNION */
SELECT
COUNT(*) AS the_count,
'the_count_a'
FROM STOCK WHERE quantity > 3
UNION ALL
SELECT
COUNT(*) AS the_count,
'the_count_b'
FROM STOCK WHERE quantity <= 30

MySQL sum of two COUNT statements

I know this has a stupid solution but, sorry, I'm little bit confused.
I have two SELECT COUNT statements. Example:
Statement 1
SELECT COUNT(softwareone) AS totalcount
FROM my_table WHERE softwareone LIKE '%typeone%'
totalcount = 3
_
Statement 2
SELECT COUNT(softwaretwo) AS totalcount
FROM my_table WHERE softwaretwo LIKE '%typeone%'
totalcout = 1
I want to sum both totals to get totalcount = 4. There is a way to do that?
Note: software type from columns "softwareone" and "softwaretwo" is of the same type (same value).
Thanks to all.
One way is to write:
SELECT SUM(CASE WHEN softwareone LIKE '%typeone%'
AND softwaretwo LIKE '%typeone%'
THEN 2
ELSE 1
END
) AS "totalcount"
FROM my_table
WHERE softwareone LIKE '%typeone%'
OR softwaretwo LIKE '%typeone%'
;
The CASE ... END expression will evaluate to 2 when both conditions are met (so that if softwareone and softwaretwo are both LIKE '%typeone%', then the row counts twice), and 1 when only one of them is. So, the SUM(CASE ... END) gives the total number of rows where the one condition is met, plus the total number of rows where the other condition is met.
You could use a
Select l1.totalcount + l2.totalcount FROM
(SELECT COUNT(softwareone) AS totalcount
FROM my_table WHERE softwareone LIKE '%typeone%') as l1,
(SELECT COUNT(softwaretwo) AS totalcount
FROM my_table WHERE softwaretwo LIKE '%typeone%') as l2