how to write this query in access 2007 - c#

select ((select SUM (Total)
from Shirt_Mes
where CustomerId =2
and Created_Date ='2016-10-05 05:25:06.000')
+ (select SUM (Total)
from Pant_Mes
where CustomerId =2
and Created_Date ='2016-10-05 05:25:06.000' )

MS Access requires a FROM clause with a table. So, let's move both to the FROM clause. There are a few other changes as well:
select s.sums + p.sump
from (select SUM(Total) as sums
from Shirt_Mes
where CustomerId = 2 and
Created_Date = #10/5/2016# -- different date format
) as s, -- Oh, it hurts that MS Access does not have `cross join`
(select SUM(Total) as sump
from Pant_Mes
where CustomerId = 2 and
Created_Date = #10/5/2016#
) as p;

Related

SQL Server looping through inside stored procedure

I have a C# windows application which is related to products. In my application we fetch the date when the product is added to the inventory. Based on the AddDate of the product, we get the age of the product in months.
Let's say the age of a product is 25 months.
int Age = 25;
for(int i = Age; i >=0; i --)
{
var result = GetProductData(DateTime.Now.AddMonth(0-i));
}
The GetProductData() method calls a stored procedure, so if the age of the product is 25 months, the stored procedure gets called 25 times.
In the stored procedure, we extract the month and year part from the DateTime and store those bits into 2 separate variables. This is how it is currently
CREATE PROCEDURE usp_GetProductData
#AppId INT,
#Date DATETIME
AS
BEGIN
DECLARE #Month INT
DECLARE #Year INT
DECLARE #ProductInstall INT
SELECT #Month = SELECT DATEPART(m, #Date)
SELECT #Year = SELECT YEAR(#Date)
SELECT #ProductInstall = (SUM(P.[AutoInstalls]) + SUM(P.[ITInstalls]))
FROM dbo.[ProductInstalls] P
INNER JOIN [User] U ON U.[UserId] = P.[UserId]
WHERE LicenseRequired = 1
AND DATEPART(m, P.[InstallDate]) = #month
AND DATEPART(year, P.[InstallDate]) = #Year
SELECT
AVG(A.[TotalRequests] - A.[TotalInstalls]) * 100 AS [ProductAverage],
#ProductInstall, #Month/#Year
FROM
dbo.[ApplicationInstalls]
/*There are few more joins and some business logic after this */
WHERE
DATEPART(m, A.[InstallDate]) = #Month
AND DATEPART(year, A.[InstallDate]) = #Year
END
Now instead of calling the stored procedure as many times as the age of product/application, I want to do it in a single request as I already have the date the application/product was added to the inventory
DECLARE #ProductAddDate
DECLARE #ProductAge
SELECT #ProductAddDate = [DateAdded] FROM dbo.[Application] WHERE [AppId] = #AppId
SELECT #ProductAge = DATEDIFF(DAY, #ProductAddDate, GETDATE())/30
Now with the product age I have, I want to loop through the below logic for every month.
SELECT
#ProductInstall = (SUM(P.[AutoInstalls]) + SUM(P.[ITInstalls]))
FROM
dbo.[ProductInstalls] P
INNER JOIN
[User] U ON U.[UserId] = P.[UserId]
WHERE
LicenseRequired = 1
AND DATEPART(m, P.[InstallDate]) = #month
AND DATEPART(year, P.[InstallDate]) = #Year
SELECT
AVG(A.[TotalRequests] - A.[TotalInstalls]) * 100 AS [ProductAverage], #ProductInstall,
#Month/#Year
FROM
dbo.[ApplicationInstalls]
/*There are few more joins and some business logic after this */
WHERE
DATEPART(m, A.[InstallDate]) = #Month
AND DATEPART(year, A.[InstallDate]) = #Year
Not sure if your core logic really represents 'application' data, or product data, but I'll keep the proc name as 'getProductData'. Here's what it does:
First, in the 'monthYears' CTE, I get the product-add-date for the application and create month and year bins that spread from the add date to the present date. This is the only 'looping' I do. Otherwise, the healthier approach is to use set-theoretical operations available in SQL Server, which are much more efficient.
Then, in the 'productInstalls' CTE, I take your logic, omit the month and year filters, and instead group by month and year to get them all at once.
I do the same for your application installs logic in the 'applicationInstalls' CTE.
Finally, I join it all together by year and month in the core query.
Here's the code:
create procedure getProductData
#AppId int
as
declare #ProductAddDate date = (
select dateAdded
from [application]
where appId = #AppId
);
with
monthYears as (
select mo = datepart(m, #productAddDate),
yr = datepart(year, #productAddDate),
i = 0
union all
select mo = datepart(m, dateAdd(m, i+1, #productAddDate)),
yr = datepart(year, dateAdd(m, i+1, #productAddDate)),
i = i+1
from monthYears
where datepart(m, dateAdd(m, i+1, #productAddDate)) <= datepart(m, getdate())
and datepart(year, dateAdd(m, i+1, #productAddDate)) <= datepart(year, getdate())
),
productInstalls as (
select mo = datepart(m, p.installDate),
yr = datepart(year, p.installDate),
ProductInstall = sum(p.autoinstalls) + sum(p.itinstalls)
from productInstalls p
join [user] u on u.userId = p.userId
where licenseRequired = 1
group by datepart(m, p.installDate),
datepart(year, p.installDate)
),
applicationInstalls as (
select mo = datepart(m, a.installDate),
yr = datepart(year, a.installDate),
ProductAverage = avg(a.totalRequests - a.totalInstalls) * 100
from applicationInstalls a
group by datepart(m, p.installDate),
datepart(year, p.InstallDate)
)
select my.yr,
my.mo,
ProductAverage = isnull(a.ProductAverage, 0),
ProductInstall = isnull(p.ProductInstall, 0)
from monthYears my
left join applicationInstalls a on my.yr = a.yr and my.mo = a.mo
left join productInstalls p on my.yr = p.yr and my.mo = p.mo;
When you get this in C#, it will be as a collection. Most likely it will be output as a DataTable or your business layer might output it as an IEnumerable or List of some type. So your looping, if necessary, will then occur in the C# code, not the SQL code.
Something like:
int appId = 0; // or whatever
foreach(var productDatum in GetProductData(appId)) {
// do something with productDatum
}
I don't have an "Answer" per se, but I do have an idea that might be worth looking deeper into. In SQL Server, there is the concept of Window Functions. Itsak Ben-Gan wrote a book on it a few years back, but you can find it by Googling - here is one site.
The con here is you have to start thinking differently to program this way. The pro is, where applicable, no recursion. The window flows down through the table on a single scan gathering the aggregates as it goes down. A few years back, I used this to determine scheduling conflicts in a large scale app, reducing time to return results from 10 - 20 seconds to about .5 seconds. You may not require this performance bump, but if you can figure out how to apply to your problem, you avoid a lot of table (or index) scans.

How to get the total count of two columns from two different tables in SQL Server?

I have 2 tables in SQL Server, Table1 and Table2.
Table1 contains the information of family head with his age and Table2 contains the information of family members with their age.
I want to get total count of age. Means if the user enter less than 23 in front end so I will display to user total count of persons less than 23 age from two tables.
My approach is like this:
alter procedure example
(#age int, #result2 int output)
as
begin
declare #result int;
declare #result1 int;
set #result = (select count(age) from Table1 where age > #age)
set #result1 = (select count(age) from Table2 where age > #age)
set #result2 = #result + #result1;
end
hvcid is the primary key column in my Table1 and hvcid is a foreign key in my Table2.
My query shown above returns the result fine. Why not do using join or single query to combine two tables and get the total count of age from two tables?
I don't know how to write using single query? Can you solve my issue?
You can use below query to get result from 2 tables :
select count(age) + (select count(age)
from Table2 where age > #age)
from Table1 where age > #age
Another way
SELECT Sum(cnt) AS total
FROM (SELECT Count(age) cnt
FROM Table1
WHERE age > #age
UNION ALL
SELECT Count(age)
FROM Table2
WHERE age > #age) a
Try this #Nag
select (COUNT(t1.age) + COUNT(t2.age)) as Result
from Table1 t1
FULL JOIN Table2 t2 on t1.hvcid = t2.hvcid
where t1.age > #age and t2.age > #age

How do I grab only the latest Invoice Number

I have Invoice Numbers that are stored as nvarchar(25).
Their Format is ‘####AA’
Where #### is the Invoice Number and AA is the Version Number (partial Order Shipping)
I cannot change the format.
I created two Scalar Functions:
CREATE FUNCTION [dbo].[fnNumbersFromStr](#str varchar(8000))
RETURNS int
AS
BEGIN
WHILE PATINDEX('%[^0-9]%',#str)> 0
SET #str = REPLACE(#str, SUBSTRING(#str, PATINDEX('%[^0-9]%', #str), 1), '')
RETURN CAST(#str AS INT)
END
And it’s brother:
CREATE FUNCTION [dbo].[fnStringFromNum](#str varchar(25))
RETURNS varchar(25)
AS
BEGIN
WHILE PATINDEX('%[^a-z]%',#str)> 0
SET #str = REPLACE(#str, SUBSTRING(#str, PATINDEX('%[^a-z]%', #str), 1), '')
RETURN #str
END
I am stalled with this script:
SELECT
strInvoiceNo,
dbo.fnNumbersFromStr(strInvoiceNo) AS [InvoiceNumber],
dbo.fnStringFromNum(strInvoiceNo) AS [InvoiceString]
FROM #TempTable
Which when runs returns:
strInvoiceNo InvoiceNumber InvoiceString
1000A 1000 A
1000B 1000 B
1000C 1000 C
1001A 1001 A
1001B 1001 B
1002AA 1002 AA
1002AB 1002 AB
1003A 1003 A
1004A 1004 A
I just can’t figure out the next step from here. I am stuck.
I would like the select to only return the latest Invoice Versions:
1000C
1001B
1002AB
1003A
1004A
Sql, Lamda or Linq will work fine for me.
Thanks in advance,
Try this:
SELECT
InvoiceNumber + MAX(InvoiceString) As strInvoiceNo
FROM
(
SELECT
dbo.fnNumbersFromStr(strInvoiceNo) AS [InvoiceNumber],
dbo.fnStringFromNum(strInvoiceNo) AS [InvoiceString]
FROM #TempTable
) As tbl
GROUP BY InvoiceNumber
I dont think you need any UDF for this, a simple windowing function query should return what you looking for.
WITH x AS
(
Select *
,ROW_NUMBER() OVER (PARTITION BY InvoiceNumber ORDER BY strInvoiceNo DESC) rn
FROM TableName
)
SELECT strInvoiceNo, InvoiceNumber, InvoiceString
FROM X
WHERE rn = 1
OR
SELECT strInvoiceNo, InvoiceNumber, InvoiceString
FROM
(
Select *
,ROW_NUMBER() OVER (PARTITION BY InvoiceNumber ORDER BY strInvoiceNo DESC) rn
FROM TableName
)x
WHERE rn = 1
Here is it in LINQ (Assuming fnStringFromNum returns a string padded on the left with spaces):
dbContext.YOURTABLE
.GroupBy(x=>UDFFunctions.fnNumbersFromStr(x.AccountNumber))
.Select(x=>x.OrderByDescending(y=>UDFFunctions.fnStringFromNum(y.AccountNumber).FirstOrDefault())
SQL (using current fnStringFromNum):
SELECT
InvoiceNumber + LTRIM(MAX(RIGHT(SPACE(20)+InvoiceString,20))) As strInvoiceNo
FROM
(
SELECT
dbo.fnNumbersFromStr(strInvoiceNo) AS [InvoiceNumber],
dbo.fnStringFromNum(strInvoiceNo) AS [InvoiceString]
FROM #TempTable
) As tbl
GROUP BY InvoiceNumber
Not necessarily the most efficient, but this will work:
select strInvoiceNo
from #TempTable T
where InvoiceString = (select max(invoicestring) from temp1 where invoicenumber = T.invoicenumber)
order by 1
Edit: Sorry....disregard. This will work off of your full result table but may not be what you actually need. Apologies.

count the number of 1st and 0's with a specific date

In my database i have column name department and employed(return type is bit - 0 or 1), i would like to count the number of employee employed in each department (there are 5 departments) for this year and rank the department who has the highest employee. I need help combining SQL query.
This is how i can calculate 0'1 and 1's SELECT COUNT(CASE Authorised WHEN 1 THEN 1 ELSE NULL END) FROM TableName;
and this is how i can select date for this year: `
SELECT distinct *
From TableName
WHERE Time BETWEEN CONVERT(Date,#Time) AND CONVERT(Date, #Time2)
How do i combine these query?
You need to use this query, the query returns all departments name and the total of employees in it.
SELECT
DEPARTMENTNAME, COUNT(*) AS TOTAL
FROM
TABLENAME
WHERE
TIME BETWEEN
CONVERT(Date,#Time)
AND
CONVERT(Date, #Time2)
GROUP BY DEPARTMENTNAME
ORDER BY COUNT(*) DESC
This is an example of how your sql should be.
declare #WhatEverYourTableNameIs Table
(
Department varchar(3),
employed bit,
employeddate date
)
Insert into #WhatEverYourTableNameIs
Values
('dem',1,'2014-1-1'),
('dem',1,'2014-2-1'),
('dem',0,'2014-2-1'),
('eem',1,'2013-2-1'),
('dem',1,'2013-2-1'),
('eem',1,'2014-2-1')
Select Department, Count(employed) AS Cnt
From #WhatEverYourTableNameIs
Where employeddate >'2013-12-31' and employed = 1
Group by Department
order by Cnt desc

Combine Multiple Select Statements from different tables

i have the this MYSQL SP that does SUm against different tables but i wanted the SP to return all the results in one table one row i tried using + to combine results from the selects but it gets error
DROP PROCEDURE IF EXISTS x.GetFinanceContent;
delimiter //
CREATE PROCEDURE x.GetFinanceContent
(
IN userId INT
)
BEGIN
(SELECT SUM(AMOUNT) AS creditTotal
FROM x.Card1
WHERE user_Id = userId and card_type=1)
+
(SELECT SUM(AMOUNT) AS debitTotal
FROM x.Card2
WHERE user_Id = userId and card_type=2)
END;//
Error Code: 1064 You have an error in
your SQL syntax; check the manual that
corresponds to your MySQL server
version for the right syntax to use
near '+ (SELECT SUM(AMOUNT) AS
debitTotal
FROM x.Card
WHERE user_Id ' at line 10 0.000 sec
SELECT
( SELECT SUM(AMOUNT) AS creditTotal
FROM x.Card1
WHERE user_Id = userId AND card_type=1
)
, ( SELECT SUM(AMOUNT) AS debitTotal
FROM x.Card2
WHERE user_Id = userId AND card_type=2
)
If you want to SUM those sums you can make query like this:
SELECT ((SELECT SUM(AMOUNT) AS creditTotal
FROM x.Card1
WHERE user_Id = userId and card_type=1) +
(SELECT SUM(AMOUNT) AS debitTotal
FROM x.Card2
WHERE user_Id = userId and card_type=2)) as total
Use union http://dev.mysql.com/doc/refman/5.0/en/union.html If you want to get one result set....
DROP PROCEDURE IF EXISTS x.GetFinanceContent;
delimiter //
CREATE PROCEDURE x.GetFinanceContent
(
IN userId INT
)
BEGIN
(SELECT SUM(AMOUNT) AS creditTotal
FROM x.Card1
WHERE user_Id = userId and card_type=1)
UNION
(SELECT SUM(AMOUNT) AS debitTotal
FROM x.Card2
WHERE user_Id = userId and card_type=2)
END;//
Although I am rusty now with SQL and too lazy to check if syntax is correct, I think it should work.

Categories