I have a table like this
Table1
=======
A B
8 5
2 9
null 4
2 5
How to find total number of rows from table1,note if any column value is null in a row then that row should be considered as 2 rows?
I have tried with count(*)*2 and nvl function it doesn't work
Try this
SELECT SUM(CASE WHEN A IS NULL OR B IS NULL THEN 2 ELSE 1 END) AS CountVal
FROM TABLE1
Fiddle Demo
O/P:
COUNTVAL
--------
5
COUNT() is rowbased.. you can tweak it using SUM() instead..
select sum(NVL2(a,NVL2(b,1,2),2)) FROM TABLE1
CASE as suggested by #Vignesh is the simplest and more readable !!
COUNT() can also done like this.. But NOT a optimal solution at all!
SELECT COUNT(1) FROM
(
SELECT NVL(a,NVL(b,1)) FROM TABLEA
UNION ALL
SELECT NVL(a,NVL(b,1)) FROM TABLEA
WHERE A OR B iS NULL
)
Related
I'm trying to do something similar to this:
SELECT SUM(
CASE WHEN (<some_condition>
AND EXISTS(SELECT 1
FROM <tableA> as tA
WHERE tA.Id = tB.tAId and
<some_other_condition>
)
) THEN 1 ELSE 0 END
) as <column_name>
FROM <tableB> as tB
I need to avoid the use of joins to achieve what I need, because I don't want to count/sum duplicates returned by the results I get through join clauses in this case. When I try to execute my query, I get the following error message:
"cannot perform an aggregate function on an expression containing an aggregate or a subquery"
I don't know what I am doing wrong.
Any help appreciated.
EDIT: I added a possible condition on the WHERE statement only to show I need to relate the columns of the outside table (tableB) with the inside table (tableA)
Here's an example of tableA and tableB and what happens when I JOIN both:
tableA: tableB: tableA JOIN tableB
Id Id tAId Time Id(A) Id(B) taId Time
1 1 1 5 1 1 1 5
2 2 2 6 2 2 2 6
3 3 2 10 2 3 2 10
4 4 3 11 3 4 3 11
5 5 4 14 4 5 4 14
6 4 13 4 6 4 13
7 4 12 4 7 4 12
8 5 10 5 8 5 10
So, when I try to count/sum some property (i.e. tableA.Id) from tableA using the results of the JOIN operation as input, I end up counting duplicates. Here's why I can't use JOIN unless I can select DISTINCT elements. I liked the answer that shows this so I'm trying to implement that with no errors.
(Note: I really appreciate all the other answers since they show possible solutions that can fit my situation)
SELECT SUM(
CASE WHEN (<some_condition>
AND tA.Id IS NOT NULL
) THEN 1 ELSE 0 END
) as <column_name>
FROM <tableB> as tB
JOIN (SELECT DISTINCT ta.Id
FROM <tableA>) as tA ON tA.Id = tB.Id AND <some_other_condition>
Since, as the message says, you cannot use a subquery in an aggregate function (SUM()), consider using a join similar to the following:
SELECT SUM(
CASE WHEN (<some_condition>
AND tA.<matching_column> IS NOT NULL
) THEN 1 ELSE 0 END
) as <column_name>
FROM <tableB> tB
LEFT JOIN <tableA> tA
ON tA.Id = tB.Id
WHERE tA.<some_other_condition>
Just a simple answer from what you provided initiall:
SELECT SUM(<column_name>) AS SumColumn
FROM (
SELECT CASE WHEN <some_condition> AND EXISTS(SELECT 1 FROM <tableA> WHERE <some_other_condition>) THEN 1 ELSE 0 END as <column_name>
FROM <tableB>
)AS SUB
Your query is an aggregation query, so the intent appears to be returning one row. So, just move all the conditions to the WHERE clause. This is my best guess as to your intent:
SELECT COUNT(*) as <column_name>
FROM <tableB> tB
WHERE (<some_condition> AND
EXISTS (SELECT 1
FROM <tableA> as tA
WHERE tA.Id = tB.Id AND <some_other_condition>
);
Suppose I have a table that contains the following:
CUS_ID A B
1 1 0
2 2 0
3 3 1
3 1 3
4 2 0
Is there a way to write a select statement and grab all the distinct cus_id? So basically it would only bring back one record for cus_id 3.
SELECT DISTINCT CUS_ID FROM table_name;
Or:
select
CUS_ID
-- columns below are optional and exist just to
-- help you understand for what reason 'group by' is needed
-- , count(A) cntA
-- , sum(B) sumB
from YourTable
group by
CUS_ID
order by
CUS_ID
UPD. I meant to comment whole lines :)
I have a table:
[letter] [Name] [status] [price]
A row1 1 11
A row1 1 15
B row2 2 9
B row2 3 23
B row2 3 30
And want to select data something like this:
SELECT letter, Name,
COUNT(*),
CASE WHEN price>10 THEN COUNT(*) ELSE NULL END
GROUP BY letter, Name
the result is:
A row1 2 2
B row2 1 null
B row2 2 2
But I want this format:
A row1 2 2
B row2 3 2
Please, help me to modify my query
Close. Probably want this instead:
SELECT letter, Name,
COUNT(*),
SUM(CASE WHEN price>10 THEN 1 ELSE 0 END)
FROM TableThatShouldHaveAppearedInTheQuestionInTheFromClause
GROUP BY letter, Name
should work. Assuming that the intention of the fourth column is to return the count of the number of rows, within each group, with a price greater than 10. It's also possible to do this as a COUNT() over a CASE then returns non-NULL and NULL results for the rows that should and should not be counted, but I find the above form easier to quickly reason about.
Since nulls are not used in aggregate functions:
SELECT letter
, name
, count(*)
, count(
case when price > 10 then 1
end
)
FROM t
GROUP BY letter, name
You were very close.
Looking to the other answers, probably this is not the best way, but it will work.
The count of the prices over 10 is made with a subquery which has a condition on price > 10 and which is joined to the current TAB record with the alias A for the same letter and name.
SELECT letter,
Name,
COUNT(*),
(SELECT COUNT(*) FROM TAB WHERE letter = A.letter and Name = A.Name WHERE price>10)
FROM TAB A
GROUP BY letter, Name
id Name claim priority
1 yatin 70 5
6 yatin 1 10
2 hiren 30 3
3 pankaj 40 2
4 kavin 50 1
5 jigo 10 4
7 jigo 1 10
this is my table and i want to arrange this table as shown below
id Name claim priority AlternateFlag
1 yatin 70 5 0
6 yatin 1 10 0
2 hiren 30 3 1
3 pankaj 40 2 0
4 kavin 50 1 1
5 jigo 10 4 0
7 jigo 1 10 0
It is sorted as alternate group of same row.
I am Using sql server 2005. Alternate flag starts with '0'. In my example First record with name "yatin" so set AlternateFlag as '0'.
Now second record has a same name as "yatin" so alternate flag would be '0'
Now Third record with name "hiren" is single record, so assign '1' to it
In short i want identify alternate group with same name...
Hope you understand my problem
Thanks in advance
Try
SELECT t.*, f.AlternateFlag
FROM tbl t
JOIN (
SELECT [name],
AlternateFlag = ~CAST(ROW_NUMBER() OVER(ORDER BY MIN(ID)) % 2 AS BIT)
FROM tbl
GROUP BY name
) f ON f.name = t.name
demo
You could use probably an aggregate function COUNT() and then HAVING() and then UNION both Table, like:
SELECT id, A.Name, Claim, Priority, 0 as AlternateFlag
FROM YourTable
INNER JOIN (
SELECT Name, COUNT(*) as NameCount
FROM YourTable
GROUP BY Name
HAVING COUNT(*) > 1 ) A
ON YourTable.Name = A.Name
UNION ALL
SELECT id, B.Name, Claim, Priority, 1 as AlternateFlag
FROM YourTable
INNER JOIN (
SELECT Name, COUNT(*) as NameCount
FROM YourTable
GROUP BY Name
HAVING COUNT(*) = 1 ) B
ON YourTable.Name = B.Name
Now, this assumes that the Names are unique meaning the names like Yatin for example although has two counts is only associated to one person.
See my SqlFiddle Demo
You can use Row_Number() function with OVER that will give you enumeration, than use the reminder of integer division it by 2 - so you'll get 1s and 0s in your SELECT or in the view.
I have a temp table populated in a sproc that is similar to this:
Company Col1 Col2 Col3 Total
Company1 4 3 2 9
Company2 1 0 3 4
Total ? ? ? ?
Is there a slick way to get the bottom total column populated with SUM of each row in one shot without having to do each column individually using sub-queries?
select sum(col1), sum(col2), sum(col3), sum(col1+col2+col3)
FROM CompanyTable
If the DBMS you use is MS SQL than be aware of how to reference the temporary table:
SELECT SUM(Col1) as TotalOfCol1,...
FROM #Company
If you are using MySQL, you can get the whole table in one query using the WITH ROLLUP feature:
SELECT Company, SUM(Col1), SUM(Col2), SUM(Col3), SUM(Col1 + Col2 + Col3)
FROM Table1
GROUP BY Company
WITH ROLLUP
Results:
'Company1' 4 3 2 9
'Company2' 1 0 3 4
'' 5 3 5 13 <--- This extra row is the column totals