how to set a range of defaults in a count query - sql

I have a simple table of values:
column1
-------
2
5
7
5
8
7
and this simple query of number count:
SELECT column1, count(column1) as counter
FROM table
GROUP BY column1
ORDER BY count(column1) DESC
The question how can I add rows with values 0 when I have a number range for example from 1 to 8.
I want to get the result like this:
column1 Counter
-------- -------
5 2
7 2
2 1
8 1
1 0 <-- Row Add
2 0 <-- Row Add
3 0 <-- Row Add
4 0 <-- Row Add
6 0 <-- Row Add
Thanks very much.

If you are willing to use more than 1 query and to put your range of numbers in a table at least temporarily then you can do this with a full outer join. To do a Full outer join in access you combine a left join and a right join using either UNION OR UNION ALL.
copy the sql from the right and left joins into a union query then add the union and the order by statements to the union query.
SELECT SpecialNumbers.Numbers, mytable.Column1, Count(mytable.Column1) AS CountOfColumn1
FROM SpecialNumbers LEFT JOIN mytable ON SpecialNumbers.Numbers = mytable.Column1
GROUP BY SpecialNumbers.Numbers, mytable.Column1
UNION
SELECT SpecialNumbers.Numbers, mytable.Column1, Count(mytable.Column1) AS CountOfColumn1
FROM SpecialNumbers RIGHT JOIN mytable ON SpecialNumbers.Numbers = mytable.Column1
GROUP BY SpecialNumbers.Numbers, mytable.Column1
ORDER BY CountOfColumn1 DESC;
Given my special numbers where 1 to 10 This turns
to

Assuming that you only wish the four missing rows added, this is not that difficult in Access, as it is easy to create a small query generating numbers from a system table:
SELECT
T.Column1,
Count(Table.[Column1]) AS [Counter]
FROM
(SELECT DISTINCT Abs([id] Mod 10) AS Column1
FROM MSysObjects
WHERE (Abs([id] Mod 10)) Between 1 And 8) As T
LEFT JOIN
[Table]
ON T.Column1 = Table.Column1
GROUP BY
T.Column1
ORDER BY
Count(Table.[Column1]) DESC,
T.Column1;
Output:

Related

How to use multiple counts in where clause to compare data of a table in sql?

I want to compare data of a table with its other records. The count of rows with a specific condition has to match the count of rows without the where clause but on the same grouping.
Below is the table
-------------
id name time status
1 John 10 C
2 Alex 10 R
3 Dan 10 C
4 Tim 11 C
5 Tom 11 C
Output should be time = 11 as the count for grouping on time column is different when a where clause is added on status = 'C'
SELECT q1.time
FROM (SELECT time,
Count(id)
FROM table
GROUP BY time) AS q1
INNER JOIN (SELECT time,
Count(id)
FROM table
WHERE status = 'C'
GROUP BY time) AS q2
ON q1.time = q2.time
WHERE q1.count = q2.count
This is giving the desired output but is there a better and efficient way to get the desired result?
Are you looking for this :
select t.*
from table t
where not exists (select 1 from table t1 where t1.time = t.time and t1.status <> 'C');
However you can do :
select time
from table t
group by time
having sum (case when status <> 'c' then 1 else 0 end ) = 0;
If you want the times where the rows all satisfy the where clause, then in Postgres, you can express this as:
select time
from t
group by time
having count(*) = count(*) filter (where status = 'C');

SQL Select from 1 table rows with 2 specific column value that are not equal

I have a table
id number name update_date
1 123 asd 08.05.18
2 412 ddd 08.05.18
3 123 dsa 14.05.18
4 125 dsa 05.05.18
Whole table consist from that rows like that. I need to select row 1 and 3 because I need different update_dates but same number. How to do that? I need to see the changes from specific Number between 2 update dates 08.05.18 and 14.05.18. I have more update dates in my table.
I tried:
SELECT *
FROM legal_entity_history a
JOIN legal_entity_history b ON a.BIN = b.BIN
WHERE ( a.update_date <> b.update_date AND
a.update_date = "08.05.18" AND
b.update_date = "14.05.18" )
A relatively simple method is:
select leh.*
from legal_entity_history leh
where exists (select 1
from legal_entity_history leh2
where leh2.number = leh.number and leh2.update_date <> leh.update_date
);
For performance, you want an index on legal_entity_history(number, update_date).
TRY THIS: Assuming that same number may not appear more than once under same update_date, so, you can achieve that using GROUP BY with HAVING as below
SELECT t.*
FROM test t
INNER JOIN (SELECT number
FROM test
GROUP BY number
HAVING COUNT(DISTINCT update_date) > 1) t1 ON t1.number = t.number
OUTPUT:
id number name update_date
1 123 asd 08.05.18
3 123 dsa 14.05.18

How to SELECT top N rows that sum to a certain amount?

Suppose:
MyTable
--
Amount
1
2
3
4
5
MyTable only has one column, Amount, with 5 rows. They are not necessarily in increasing order.
How can I create a function, which takes a #SUM INT, and returns the TOP N rows that sum to this amount?
So for input 6, I want
Amount
1
2
3
Since 1 + 2 + 3 = 6. 2 + 4 / 1 + 5 won't work since I want TOP N ROWS
For 7/8/9/10, I want
Amount
1
2
3
4
I'm using MS SQL Server 2008 R2, if this matters.
Saying "top N rows" is indeed ambiguous when it comes to relational databases.
I assume that you want to order by "amount" ascending.
I would add a second column (to a table or view) like "sum_up_to_here", and create something like that:
create view mytable_view as
select
mt1.amount,
sum(mt2.amount) as sum_up_to_here
from
mytable mt1
left join mytable mt2 on (mt2.amount < mt1.amount)
group by mt1.amount
or:
create view mytable_view as
select
mt1.amount,
(select sum(amount) from mytable where amount < mt1.amount)
from mytable mt1
and then I would select the final rows:
select amount from mytable_view where sum_up_to_here < (some value)
If you don't bother about performance you may of course run it in one query:
select amount from
(
select
mt1.amount,
sum(mt2.amount) as sum_up_to_here
from
mytable mt1
left join mytable mt2 on (mt2.amount < mt1.amount)
group by mt1.amount
) t where sum_up_to_here < 20
One approach:
select t1.amount
from MyTable t1
left join MyTable t2 on t1.amount > t2.amount
group by t1.amount
having coalesce(sum(t2.amount),0) < 7
SQLFiddle here.
In Sql Server you can use CDEs to make it pretty simple to read.
Here is a CDE I did to sum up totals used in sequence. The CDE is similar to the joins above, and holds the total up to any given index. Outside of the CDE I join it back to the original table so I can select it along with other fields.
;with summrp as (
select m1.idx, sum(m2.QtyReq) as sumUsed
from #mrpe m1
join #mrpe m2 on m2.idx <= m1.idx
group by m1.idx
)
select RefNum, RefLineSuf, QtyReq, ProjectedDate, sumUsed from #mrpe m
join summrp on summrp.idx=m.idx
In SQL Server 2012 you can use this shortcut to get a result like Grzegorz's.
SELECT amount
FROM (
SELECT * ,
SUM(amount) OVER (ORDER BY amount ASC) AS total
from demo
) T
WHERE total <= 6
A fiddle in the hand... http://sqlfiddle.com/#!6/b8506/6

Returning several rows from a single query, based on a value of a column

Let's say I have this table:
|Fld | Number|
1 5
2 2
And I want to make a select that retrieves as many Fld as the Number field has:
|Fld |
1
1
1
1
1
2
2
How can I achieve this? I was thinking about making a temporary table and instert data based on the Number, but I was wondering if this could be done with a single Select statement.
PS: I'm new to SQL
You can join with a numbers table:
SELECT Fld
FROM yourtable
JOIN Numbers
ON yourtable.Number <= Numbers.Number
A numbers table is just a table with a list of numbers:
Number
1
2
3
etc...
Not an great solution (since you still query your table twice, but maybe you can work from it)
SELECT t1.fld, t1.number
FROM table t1, (
SELECT ROWNUM number FROM dual
CONNECT BY LEVEL <= (SELECT MAX(number) FROM t1)) t2
WHERE t2.number<=t1.number
It generates maximum amount of rows needed and then filters it by each row.
I don't know if your RDBMS version supports it (although I rather suspect it does), but here is a recursive version:
WITH remaining (fld, times) as (SELECT fld, 1
FROM <table>
UNION ALL
SELECT a.fld, a.times + 1
FROM remaining as a
JOIN <table> as b
ON b.fld = a.fld
AND b.number > a.times)
SELECT fld
FROM remaining
ORDER BY fld
Given your source data table, it outputs this (count included for verification):
fld times
=============
1 1
1 2
1 3
1 4
1 5
2 1
2 2

Add Column values in sql server query

I have result of two queries like:
Result of query 1
ID Value
1 4
2 0
3 6
4 9
Result of query 2
ID Value
1 6
2 4
3 0
4 1
I want to add values column "Value" and show final result:
Result of Both queries
ID Value
1 10
2 4
3 6
4 10
plz guide me...
select id, sum(value) as value
from (
select id, value from query1
uninon all
select id, value from query2
) x
group by id
Try using a JOIN:
SELECT
T1.ID,
T1.Value + T2.Value AS Value
FROM (...query1...) AS T1
JOIN (...query2...) AS T2
ON T1.Id = T2.Id
You may also need to consider what should happen if there is an Id present in one result but not in the other. The current query will omit it from the results. You may want to investigate OUTER JOIN as an alternative.
A not particularly nice but fairly easy to comprehend way would be:
SELECT ID,SUM(Value) FROM
(
(SELECT IDColumn AS ID,ValueColumn AS Value FROM TableA) t1
OUTER JOIN
(SELECT IDColumn AS ID,ValueColumn AS Value FROM TableB) t2
) a GROUP BY a.ID
It has the benefits of
a) I don't know your actual table structure so you should be able to work out how to get the two 'SELECT's working from your original queries
b) If ID doesn't appear in either table, that's fine