Assign variable value within select, among other columns - sql

I am aware that you can assign a value to a variable within a select by going
SELECT #blahBlah = (tbl.ProductGroup)
FROM tbl
Ok, now what I need to do is as follow.
Each account/user has a set number of transactions allowed every day; eg. Account 1 can do 5 transactions and Account 2 can do 3.
So in a select that will determine whether this account has overshot its limit and by how many, we have numerous inSelect calculations to produce column data.
The problem is that we now have about 4 columns that will each do a nested select to get the limits from another table, in order to produce a value for the current one.
What would be ideal is to assign these limits to a #variable in the select statement and to only reference that variable within said statement if needed.
To give a brief example (not actual logic):
SELECT
#Limit = (SELECT Limit From tClient Where tClient.clientId = tbl.ClientId),
(select count(*) from batch where batchItemCount > #limit) AS BadBatches,
....
FROM TBL
You get the picture.
Is there some method to pull this off?

Yes, you can use a Common Table Expression(CTE) to do these sort of things. The following is the basic idea that you can tweak to get it work for your case:
;WITH limtis AS
(
SELECT Limit, ClientId
From tClient
Where tClient.clientId = tbl.ClientId
)
select ...
from batch
INNER JOIN Limtis On ...
WHERE ...
Hope you got the picture.

Try something like this
select clientid from tClient as t1 inner join batch as t2
on t1.clientId=t2.clientId
group by clientId
having sum(batchItemCount)>sum(limit)

Related

Expression "neither grouped nor aggregated" in BigQuery, how to include it without having to group by it?

I have this block of code:
(SELECT SELL_STR.SELL_STR_NBR, DATES.PSTD_FSCL_YR_WK, count(*) as WKLY_DLVRY--, WORK_ORD_NBR
from `analytics-df-thd.DFS.FACTS_DLY_DELV_STATS` A
inner join R1
on r1.FSCL_YR_WK = A.DATES.PSTD_FSCL_YR_WK
group by SELL_STR.SELL_STR_NBR, DATES.PSTD_FSCL_YR_WK
)
I need to add WORK_ORD_NBR to the SELECT so I can later join it
select
WKLY_DLVRY.WKLY_DLVRY
...
from table1 a
join
WKLY_DLVRY
on WKLY_DLVRY.WORK_ORD_NBR = a.WORK_ORD_NBR
However when added to WKLY_DLVRY, I receive this error:
SELECT list expression references column WORK_ORD_NBR which is neither grouped nor aggregated at
I have read many threads and they didn't give me many options, only suggesting that WORK_ORD_NBR must be grouped, however that changes the count. I appreciate any help
You can keep a column without grouping like below.
For more information please check here.
SELECT
count(*) as WKLY_DLVRY,
ARRAY_AGG(
STRUCT(WORK_ORD_NBR)
-- ORDER BY [column] DESC LIMIT 1 -- if you want to distinguish multiple values
)[OFFSET(0)].*,
FROM ~

How to select top multiple of 10 entries?

How to select top multiple of 10 entries?
I have a data in SQL table that is meaningful if only seen as bunch of 10 entries. I want to write a query that does this for ex. Select top 10*n from table where condition.
If for ex. 53 entries satisfy condition, I want only 50 to be seen and last 3 to be discarded.
Plz help.
Kbv
How about:
declare #rows int;
set #rows = ((select count(*) from table where condition)/10)*10
select top #rows * from table where condition
Try this:
with CTE AS (
SELECT * FROM Table WHERE Condition
)
Select top(((SELECT COUNT(*) FROM CTE)/10)*10) * From CTE
Please consider the following...
SELECT orderField,
field1,
...
FROM tblTable
WHERE condition
ORDER BY orderField
LIMIT 10 * numberOfGroups;
When constructing your query first decide which fields you want. In a simple one table query you can use SELECT * fairly safely, but if you are referring to a JOINed dataset then you should consider specifying which fields you are going to use and assigning aliases to those fields.
Make sure that whatever your orderField or orderFields are called they are covered by a wildcard such as * or by being explicitly specified.
The above code first selects all records that meet your criteria. It then sorts the resulting list based upon which field or fields you specify for ORDER BY. Note : The above assumes that you are sorting based upon existing values in your table. If you need to sort based on computed values then another (minor) level of complexity may need to be added.
LIMIT will then grab the first specified number of records from the sorted list. LIMIT accepts simply computed values such as 2 * 2 or 10 * numberOfGroups, where numberOfGroups is a variable set previously in the code or a value that explicitly replace numberOfGroups (i.e. 10 * #numberOfGroups where #numberOfGroups has previously been set to 5 or 10 * 5).
If you have any questions or comments, then please feel free to post a Comment accordingly.

SQL get next entry from known ID in a single query

I was wondering how would I get the data for the next row in an SQL database, assuming I know the ID for the current entry and the table is ordered by ID.
Normally, when ordering by ID, one would think that to get the prev/next entry, you just need to substract/add 1 to the variable holding the ID, and run the SELECT query with the new ID, but this poses a problem when there are holes in the table, with ID's like so:
13,14,18,21...
And so on.
A way to do it would be by looping in your programming language, running a query and adding 1 every time it runs until it finds a row, but that could be potentially taxing to the database. Is there a way to find it in just a single query?
I was thinking about this being a plausible problem, considering I even thought about it for a second. So I thought of sharing my solution here!
What I would do to solve this, is to create a new query WHERE the new id is less/greater than the old one, like so:
SELECT *
FROM myTable t
WHERE t.id > 27
ORDER BY t.id
LIMIT 1
By doing this and limiting the results to 1, you can guarantee that you will get the entry that comes after 27.
This should also work for date orderings.
How about this:
Select MIN(myTable.Id)
FROM myTable
WHERE myTable.Id > 27
Get the next id number with min(). The next id after, say, 21 would be given by this query.
select min(test_id) as next_test_id
from test
where test_id > 21
Join that to the original table to get the row for that id number.
select *
from test
inner join (select min(test_id) as next_test_id
from test
where test_id > 3 ) t2
on test.test_id = t2.next_test_id

Combining the results of two SQL queries as separate columns

I have two queries which return separate result sets, and the queries are returning the correct output.
How can I combine these two queries into one so that I can get one single result set with each result in a separate column?
Query 1:
SELECT SUM(Fdays) AS fDaysSum From tblFieldDays WHERE tblFieldDays.NameCode=35 AND tblFieldDays.WeekEnding=?
Query 2:
SELECT SUM(CHdays) AS hrsSum From tblChargeHours WHERE tblChargeHours.NameCode=35 AND tblChargeHours.WeekEnding=?
Thanks.
You can aliasing both query and Selecting them in the select query
http://sqlfiddle.com/#!2/ca27b/1
SELECT x.a, y.b FROM (SELECT * from a) as x, (SELECT * FROM b) as y
You can use a CROSS JOIN:
SELECT *
FROM ( SELECT SUM(Fdays) AS fDaysSum
FROM tblFieldDays
WHERE tblFieldDays.NameCode=35
AND tblFieldDays.WeekEnding=1) A -- use you real query here
CROSS JOIN (SELECT SUM(CHdays) AS hrsSum
FROM tblChargeHours
WHERE tblChargeHours.NameCode=35
AND tblChargeHours.WeekEnding=1) B -- use you real query here
You could also use a CTE to grab groups of information you want and join them together, if you wanted them in the same row. Example, depending on which SQL syntax you use, here:
WITH group1 AS (
SELECT testA
FROM tableA
),
group2 AS (
SELECT testB
FROM tableB
)
SELECT *
FROM group1
JOIN group2 ON group1.testA = group2.testB --your choice of join
;
You decide what kind of JOIN you want based on the data you are pulling, and make sure to have the same fields in the groups you are getting information from in order to put it all into a single row. If you have multiple columns, make sure to name them all properly so you know which is which. Also, for performance sake, CTE's are the way to go, instead of inline SELECT's and such. Hope this helps.
how to club the 4 query's as a single query
show below query
total number of cases pending + 2.cases filed during this month ( base on sysdate) + total number of cases (1+2) + no. cases disposed where nse= disposed + no. of cases pending (other than nse <> disposed)
nsc = nature of case
report is taken on 06th of every month
( monthly report will be counted from 05th previous month to 05th present of present month)

Assistance with SQL statement

I'm using sql-server 2005 and ASP.NET with C#.
I have Users table with
userId(int),
userGender(tinyint),
userAge(tinyint),
userCity(tinyint)
(simplified version of course)
I need to select always two fit to userID I pass to query users of opposite gender, in age range of -5 to +10 years and from the same city.
Important fact is it always must be two, so I created condition if ##rowcount<2 re-select without age and city filters.
Now the problem is that I sometimes have two returned result sets because I use first ##rowcount on a table. If I run the query.
Will it be a problem to use the DataReader object to read from always second result set? Is there any other way to check how many results were selected without performing select with results?
Can you simplify it by using SELECT TOP 2 ?
Update: I would perform both selects all the time, union the results, and then select from them based on an order (using SELECT TOP 2) as the union may have added more than two. Its important that this next select selects the rows in order of importance, ie it prefers rows from your first select.
Alternatively, have the reader logic read the next result-set if there is one and leave the SQL alone.
To avoid getting two separate result sets you can do your first SELECT into a table variable and then do your ##ROWCOUNT check. If >= 2 then just select from the table variable on its own otherwise select the results of the table variable UNION ALLed with the results of the second query.
Edit: There is a slight overhead to using table variables so you'd need to balance whether this was cheaper than Adam's suggestion just to perform the 'UNION' as a matter of routine by looking at the execution stats for both approaches
SET STATISTICS IO ON
Would something along the following lines be of use...
SELECT *
FROM (SELECT 1 AS prio, *
FROM my_table M1 JOIN my_table M2
WHERE M1.userID = supplied_user_id AND
M1.userGender <> M2.userGender AND
M1.userAge - 5 >= M2.userAge AND
M1.userAge + 15 <= M2.userAge AND
M1.userCity = M2.userCity
LIMIT TO 2 ROWS
UNION
SELECT 2 AS prio, *
FROM my_table M1 JOIN my_table M2
WHERE M1.userID = supplied_user_id AND
M1.userGender <> M2.userGender
LIMIT TO 2 ROWS)
ORDER BY prio
LIMIT TO 2 ROWS;
I haven't tried it as I have no SQL Server and there may be dialect issues.