T-SQL QUERY , COUNT WITH TRAILER RECORD - sql

i have a code which starts with Alert procedure and follows up with header , detail and trailer statements , where as i used select distinct for header , detail and in between both header and detail there is union command , so i was wondering if i could get the total number of records from header and detail in trailer row in specific column .. for now i have used
CONVERT(bigint, count(*) ) as Recordcount,
but it is displaying as 498 rows .. but we originally have 475 rows about trailer row . i think it is counting total number of sql query rows ..

COUNT(*) does count the total number of rows in a dataset; including any rows that are completely made up of the value NULL. Take, for example:
WITH VTE AS(
SELECT CONVERT(int,NULL) AS N
UNION ALL
SELECT CONVERT(int,NULL) AS N
UNION ALL
SELECT CONVERT(int,NULL) AS N
UNION ALL
SELECT CONVERT(int,NULL) AS N
UNION ALL
SELECT CONVERT(int,NULL) AS N
UNION ALL
SELECT 1 AS N)
SELECT COUNT(*)
FROM VTE;
Notice this returns 6, not 1. If you wanted the value 1, then you'd need to use COUNT(N).
Without sample data, this is pure guesswork, but i imagine you need to use COUNT with a CASE expression, to only include rows that aren't header or footers. This is pseudo-SQL, however, it'll be something like:
COUNT(CASE WHEN <<Some expression that determines a row instead a header/footer>> THEN 1 END)
Also, there's no reason to use CONVERT(BIGINT,COUNT(<<expr>>). If you're doing a count that might return more than 2^31-1 rows, then use COUNT_BIG. If you're not going to be returning more than 2^31-1 rows then just use COUNT (you're returning <500 rows, so literally no reason to use a bigint).

Related

Ms Access query for returning a set number of records based on two criterias

I have an MS Access query which returns records based on the following criterias:
1. Returns records where ID numbers IN[2,15,30...] this is a list of 106 numbers.
2. Returns all records NOT LIKE "** LQ **". This is currently returning 10 records.
I want this query to always return 116 records but the number that will always be changing is the number of LQ records. So instead of always adjusting the list of 106 records to accomodate for the number of LQ records is there a way to run a query which first pulls all LQ records and then fills in the gap to get to 116 with random records from the list of 106?
So since you are sure that you will get 106 records always from the filter
where ID_numbers IN [2,15,30...]
limit the Like filter output to top 10, and Union All the 2 sets
Select top 10 *
From #t
where FldContainingLQ NOT LIKE "** LQ **"
Union All
Select *
From #t
where ID_numbers IN [2,15,30...]
Also be cautious about the
impact of having Union and Union All
if the NOT LIKE "** LQ **" did not return 10 records as expected situation
If I understand correctly, this is about ordering the explicit list before the rest of the rows. You can use conditional logic in the order by:
select t.*
from t
order by iif(id in (2, 15, 30, . . . ), 1, 2)
Below query will adjust to return 10 records from ID condition if the records returned by LQ is less than 10.
Select * from
--Query 1 will return 10 records IF NOT LIKE **LQ** has 10 records that will be returned , else return 10 rows for ID condition
--When **LQ** returns less than 10 accordingly records for ID condition will be returned
(Select top 10 *
From
(Select *
From t
where Colmn NOT LIKE "** LQ **"
Union All
Select *
From t
where ID IN (2,15,30...))) as tab
Union ALL
Select *
From t
where ID IN (2,15,30...)

How can I convert 2 row into column in tsql?

I have 2 row data which I want to make it to be 2 column,
I tried union syntax but it didn't work.
Here is the data I have:
breed 1 breed2
I tried to convert it with this sql
select a.breed union a.breed
but it didn't work.
Here is what you want from the SQL:
breed1,breed2
SELECT
[breed1],
[breed2]]
FROM
(
SELECT 'breed1' myColumn
union
select 'breed2'
) AS SourceTable
PIVOT
(
AVG(mySecondColumn) FOR
myColumn IN ([breed1], [breed2]])
) AS PivotTable;
You can use a self join. This needs a way to pair rows together (so if you have four rows you get 1 and 2 in one result and 3 and 4 in the other rather than another combination).
I'm going to assume you have sequentially numbered rows in an Id column and an odd numbered row is paired with the one greater even Id:
select odd.Data as 'First', even.Data as 'Second'
from TheData odd
inner join TheData even on odd.Id+1 = even.Id
where odd.Id % 2 = 1;
More generally for more columns use of pivot is more flexible.
How about an aggregation query?
select min(breed) as breed1, max(breed) as breed2
from t;

Postgresql: Query to know which fraction of the values are larger/smaller

I would like to query my database to know which fraction/percentage of the elements of a table are larger/smaller than a given value.
For instance, let's say I have a table shopping_list with the following schema:
id integer
name text
price double precision
with contents:
id name price
1 banana 1
2 book 20
3 chicken 5
4 chocolate 3
I am now going to buy a new item with price 4, and I would like to know where this new item will be ranked in the shopping list. In this case the element will be greater than 50% of the elements.
I know I can run two queries and count the number of elements, e.g.:
-- returns = 4
SELECT COUNT(*)
FROM shopping_list;
-- returns = 2
SELECT COUNT(*)
FROM shopping_list
WHERE price > 4;
But I would like to do it with a single query to avoid post-processing the results.
if you just want them in single query use UNION
SELECT COUNT(*), 'total'
FROM shopping_list
UNION
SELECT COUNT(*),'greater'
FROM shopping_list
WHERE price > 4;
The simplest way is to use avg():
SELECT AVG( (price > 4)::float)
FROM shopping_list;
One way to get both results is as follows:
select count(*) as total,
(select count(*) from shopping_list where price > 4) as greater
from shopping_list
It will get both results in a single row, with the names you specified. It does, however, involve a query within a query.
I found the aggregate function PERCENT_RANK which does exactly what I wanted:
SELECT PERCENT_RANK(4) WITHIN GROUP (ORDER BY price)
FROM shopping_list;
-- returns 0.5

How to get three count values from same column using SQL in Access?

I have a table that has an integer column from which I am trying to get a few counts from. Basically I need four separate counts from the same column. The first value I need returned is the count of how many records have an integer value stored in this column between two values such as 213 and 9999, including the min and max values. The other three count values I need returned are just the count of records between different values of this column. I've tried doing queries like...
SELECT (SELECT Count(ID) FROM view1 WHERE ((MyIntColumn BETWEEN 213 AND 9999));)
AS Value1, (SELECT Count(ID) FROM FROM view1 WHERE ((MyIntColumn BETWEEN 500 AND 600));) AS Value2 FROM view1;
So there are for example, ten records with this column value between 213 and 9999. The result returned from this query gives me 10, but it gives me the same value of 10, 618 times which is the number of total records in the table. How would it be possible for me to only have it return one record of 10 instead?
Use the Iif() function instead of CASE WHEN
select Condition1: iif( ), condition2: iif( ), etc
P.S. : What I used to do when working with Access was have the iif() resolve to 1 or 0 and then do a SUM() to get the counts. Roundabout but it worked better with aggregation since it avoided nulls.
SELECT
COUNT(CASE
WHEN MyIntColumn >= 213 AND MyIntColumn <= 9999
THEN MyIntColumn
ELSE NULL
END) AS FirstValue
, ??? AS SecondValue
, ??? AS ThirdValue
, ??? AS FourthValue
FROM Table
This doesn't need nesting or CTE or anything. Just define via CASE your condition within COUNTs argument.
I dont really understand what You want in the second, third an fourth column. Sounds to me, its very similar to the first one.
Reformatted, your query looks like:
SELECT (
SELECT Count(ID)
FROM view1
WHERE MyIntColumn BETWEEN 213 AND 9999
) AS Value1
FROM view1;
So you are selecting a subquery expression that is not related to the outer query. For each row in view1, you calculate the number of rows in view1.
Instead, try to do the calculation once. You just have to remove your outer query:
SELECT Count(ID)
FROM view1
WHERE MyIntColumn BETWEEN 213 AND 9999;
OLEDB Connection in MS Access does not support key words CASE and WHEN .
You can only use iif() function to count two, three.. values in same columns
SELECT Attendance.StudentName, Count(IIf([Attendance]![Yes_No]='Yes',1,Null)) AS Yes, Count(IIf([Attendance]![Yes_No]='No',1,Null)) AS [No], Count(IIf([Attendance]![Yes_No]='Not',1,Null)) AS [Not], Count(IIf([Attendance]![Yes_No],1,Null)) AS Total
FROM Attendance
GROUP BY Attendance.StudentName;

Split a query result based on the result count

I have a query based on basic criteria that will return X number of records on any given day.
I'm trying to check the result of the basic query then apply a percentage split to it based on the total of X and split it in 2 buckets. Each bucket will be a percentage of the total query result returned in X.
For example:
Query A returns 3500 records.
If the number of records returned from Query A is <= 3000, then split the 3500 records into a 40% / 60% split (1,400 / 2,100).
If the number of records returned from Query A is >=3001 and <=50,000 then split the records into a 10% / 90% split.Etc. Etc.
I want the actual records returned, and not just the math acting on the records that returns one row with a number in it (in the column).
I'm not sure how you want to display different parts of the resulting set of rows, so I've just added additional column(part) in the resulting set of rows that contains values 1 indicating that row belongs to the first part and 2 - second part.
select z.*
, case
when cnt_all <= 3000 and cnt <= 40
then 1
when (cnt_all between 3001 and 50000) and (cnt <= 10)
then 1
else 2
end part
from (select t.*
, 100*(count(col1) over(order by col1) / count(col1) over() )cnt
, count(col1) over() cnt_all
from split_rowset t
order by col1
) z
Demo #1 number of rows 3000.
Demo #2 number of rows 3500.
For better usability you can create a view using the query above and then query that view filtering by part column.
Demo #3 using of a view.