price c_melli cost_teacher
150000 5099572650 1
170000 5099572650 1
170000 5099572650 1
150000 0015601218 1
170000 0015601218 1
200000 0015601218 1
200000 0015601218 2
200000 0015601218 2
200000 0015601218 1
select * from
(select * from temp) as s
PIVOT
(
SUM(price)
FOR [cost_teacher] IN ([1],[2],[3])
) as p1
result is:
c_melli 1 2 3
0015601218 720000 400000 NULL
5099572650 490000 NULL NULL
I want to add column with count of 1 and 2 and 3
and add column with sum of each row
and add a row to end for calculate each columns.
Please help me.
Select t.c_melli, s.[1], c.[1], s.[2], c.[2], s[3], c.[3], s.[1]+s.[2]+s.[3] as sumRow from (select distinct c_Melli from temp) t
inner join(
select * from
(select * from temp) as s
PIVOT
(
SUM(price)
FOR [cost_teacher] IN ([1],[2],[3])
) as p1
) s on s.mellicode = t.mellicode
inner join(
select * from
(select * from temp) as s
PIVOT
(
Count(price)
FOR [cost_teacher] IN ([1],[2],[3])
) as p1
) c on c.mellicode = t.mellicode
I usually advise that people do their summary lines in the reporting tool or web page or wherever the data is going. It's too easy to get the total line mixed in with the detail lines if the record order isn't rigidly defined.
But what you want is possible, and here's a way to do it:
;
-- Turning the original query into a CTE allows us to easily re-use it in the query
with detail as (
select c_melli
, [1]
, [2]
, [3]
from
(select * from temp) as s
PIVOT
(
SUM(price)
FOR [cost_teacher] IN ([1],[2],[3])
) as p1
)
-- The first SELECT retrieves the detail pivoted row, plus a calculated total of all columns.
select c_melli
, [1]
, [2]
, [3]
, row_total = COALESCE([1],0) + COALESCE([2],0) + COALESCE([3],0)
from detail
-- using "union all" rather than "union" because "union all" skips the
-- duplicate-removal step (which we don't need) and is therefore faster.
union all
-- The section SELECT summarizes all of the detail rows.
select 'total' -- this assumes c_melli is a string; if not, use something else
, SUM([1])
, SUM([2])
, SUM([3])
, SUM(COALESCE([1],0) + COALESCE([2],0) + COALESCE([3],0))
from detail
Disclaimer: I did this from memory and have not tested it.
How about using WITH ROLLUP?
SELECT CASE WHEN (GROUPING(c_melli) = 1) THEN 'Total'
ELSE ISNULL(c_melli, 'UNKNOWN')
END as c_melli,
[1], [2], [3], [1]+[2]+[3] as Total
FROM
(select * from temp) as s
PIVOT
(
SUM(price)
FOR [cost_teacher] IN ([1],[2],[3])
) as p1
GROUP BY c_melli WITH ROLLUP
Related
I have a table with customer transactions that I'm trying to aggregate by customer and department.
Cust_id trans_num sku dept qty price
123 234 345 1 2 15.99
123 345 887 1 1 12.99
123 678 445 2 1 21.89
234 345 998 1 1 7.99
In SQL I'd do something like this:
SELECT Cust_id
, SUM(CASE WHEN dept = 1 THEN (price * qty) ELSE 0 END ) dept_1_spend
, SUM(CASE WHEN dept = 2 THEN (price * qty) ELSE 0 END ) dept_2_spend
from tab1
group by Cust_id
The U-SQL docs here mention ? as the C# equivalent but I'm not sure how to SUM the values.
What's the equivalent in U-SQL?
You can try ternary operator in C#:
SELECT Cust_id
, SUM(dept == 1 ? price * qty : 0) AS dept_1_spend
, SUM(dept == 2 ? price * qty : 0) AS dept_2_spend
from tab1
group by Cust_id
You can also you the U-SQL PIVOT operator, eg
#tab1 =
SELECT *
FROM(
VALUES
(123,234,345,1,2,15.99),
(123,345,887,1,1,12.99),
(123,678,445,2,1,21.89),
(234,345,998,1,1,7.99)) AS T(Cust_id,trans_num,sku,dept,qty,price);
#res =
SELECT Cust_id,
SUM([1]) AS dept_1_spend,
SUM([2]) AS dept_2_spend
FROM
(
SELECT Cust_id, dept, price * qty AS spend
FROM #tab1
) AS t
PIVOT (SUM(spend) FOR dept IN ( 1 AS [1], 2 AS [2] )
) AS pvt
GROUP BY Cust_id;
OUTPUT #res
TO "/output/sum_case.csv"
USING Outputters.Csv();
More information on U-SQL PIVOT available here.
You can even use the SQL's CASE expression. You will need the C# == and use AS to designate the column aliases and use upper-case for the keywords. But otherwise looks like your query:
#tab1 =
SELECT *
FROM(
VALUES
(123,234,345,1,2,15.99),
(123,345,887,1,1,12.99),
(123,678,445,2,1,21.89),
(234,345,998,1,1,7.99)) AS T(Cust_id,trans_num,sku,dept,qty,price);
#res =
SELECT Cust_id,
SUM(CASE WHEN dept == 1 THEN(price * qty) ELSE 0 END) AS dept_1_spend,
SUM(CASE WHEN dept == 2 THEN(price * qty) ELSE 0 END) AS dept_2_spend
FROM #tab1
GROUP BY Cust_id;
OUTPUT #res
TO "/output/sum_case.csv"
USING Outputters.Csv();
I personally prefer the C# ternary if.
I want to get alternate series of records using SQL Server.
For example :
I want to skip first 10 records (1 to 10) in sequence and get other 10 records (11 to 20) after that I want to skip next 10 records (21 to 30) and get another next 10 records (31 to 40)
I have done for alternate rows as below...
SELECT ROW, EmployeeID
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY EmployeeID) AS ROW, *
FROM Employee) A
WHERE
ROW % 2 = 0
But in case of my requirement above logic will not work. Please help me to make above thing works..
Linq will also accepted
Thanks
SELECT ROW, EmployeeID
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY EmployeeID) AS ROW, *
FROM Employee) A
WHERE
((ROW - 1)/10) % 2 = 1
I have done above of your requirement like below (Example).
Generated 1200 number sequentially from 1 to 1200 like below
;WITH CTE
AS
(
SELECT 1 PERIOD_SID
UNION ALL
SELECT PERIOD_SID+1 FROM CTE WHERE PERIOD_SID<1200
)
SELECT * INTO #PERIOD1 FROM CTE
OPTION(MAXRECURSION 0)
After this i have find alternative numbers like you have mentioned in your query
SELECT PERIOD_SID FROM
(
SELECT CASE
WHEN PERIOD_SID%10 <> 0 THEN PERIOD_SID / 10
WHEN PERIOD_SID%10 = 0 THEN ( PERIOD_SID / 10 ) - 1
END RNO,
PERIOD_SID
FROM #PERIOD1 )A
WHERE RNO%2=0
so if you have sequential numbers in your query (If you dont have generate using rownumber) then apply above logic.
Your query need to convert like below.
SELECT EMPLOYEEID
FROM (SELECT Row_number()
OVER (
ORDER BY EMPLOYEEID)AS ROW,
*
FROM EMPLOYEE) A
WHERE ( CASE
WHEN RNO%10 <> 0 THEN RNO / 10
WHEN RNO%10 = 0 THEN ( RNO / 10 ) - 1
END )%2 = 0
may be you can try this
SELECT ROW, EmployeeID FROM(
SELECT ROW_NUMBER()OVER (ORDER BY EmployeeID)AS ROW,* FROM Employee)
A WHERE ((ROW - (ROW%10))/10) % 2 = 1
Don't if this works or not coz I dont have sql server to run. Please show the error/result after running this query.
Ask if any doubt.
I want to select multiple row on a table. But I want to select fields every row too. Here is sample table :
---------------------
OrNo | Name | value
---------------------
1154 | Michael | 41
1154 | Rico | 24
1487 | Alex | 21
1487 | Leo | 27
I want to select based where "Orno" code which in the table is multiple. so I want to get every name and value on 1 of "OrNO".
For an example, I want to select where OrNO 1154. How to select all of name and value from that code? How to used sql data reader for read them?
Edit:
Based answered, I'm sorry, I want to execute on behind code, like sqldatareader with C#/VB.Net. I dont know how to execute them on behind code to store to varriable.
Thank you
SELECT *
FROM MyTable
WHERE OrNo IN
(
SELECT OrNo
FROM
(
SELECT OrNo, COUNT(*) AS RecordCount
FROM MyTable
GROUP BY OrNo
) A
WHERE RecordCount > 1
)
You want to return duplicate records per OrNo, so count per OrNo and only return records with a count > 1.
select orno, name, value
from
(
select orno, name, value, count(*) over (partition by orno) as cnt
from mytable
)
where cnt > 1
order by orno;
It's hard to understand your question.
Are you searching for the SQL Statement? If so, I would suggest:
SELECT *
FROM <TABLE_NAME>
WHERE OrNo IN
(
SELECT OrNo
FROM <TABLE_NAME>
GROUP BY OrNo
HAVING COUNT(*) > 1
)
Sorry, #jmcilhinney was faster here.
And one more, with ties
with t as (
select * from (values
(1154,'Michael',41),
(1154,'Rico',24),
(1199,'Mary',25),
(1487,'Alex',21),
(1487,'Leo',27)) t(OrNo, Name, value )
)
select top(1) with ties OrNo, Name, value
from t
order by
case count(*) over (partition by OrNo ) when 1 then 1 else 0 end
I have a problem, in example: I have a range of ids of integers (from 1 to 1000), this range supposed to be ids in a SQL Server table, and I want to detect which numbers of this range are not in the table, and sorry for my bad english, thank you
another simpler option would be to use the following query
SELECT number
FROM master..spt_values
WHERE number BETWEEN 1 AND 1000
AND NOT EXISTS ( SELECT 1
FROM Your_Table t --<-- your table where you are checking
WHERE t.ID = number) -- the missing values
GROUP BY number
The above solution is only good if you are looking for around 1000 values. For more values you would need to modify it little bit, something like
-- Select the maximum number or IDs you want to check
DECLARE #Max_Num INT = 10000;
;WITH CTE AS
(
SELECT TOP (#Max_Num) ROW_NUMBER() OVER ( ORDER BY (SELECT NULL)) numbers
FROM master..spt_values v1 cross join master..spt_values v2
)
SELECT c.numbers
FROM CTE c
WHERE NOT EXISTS (SELECT 1
FROM Your_table t
WHERE t.ID = c.numbers)
One way to find "holes" is to generate a list of all possible values and then look for the ones that aren't there. If you can survive with a list of a missing value and then the number of subsequent values following it, you can do this with another method.
SQL Server 2012+ supports lead() and lag(). The following gets almost everything, except for initial missing values:
select t.id + 1 as missingid,
(coalesce(t.nextid, 1000) - t.id - 1) as nummissing
from (select t.*, lead(t.id) over (order by t.id) as nextid
from table t
t.id between 1 and 1000
) t
where t.nextid > t.id + 1 or
(t.nextid is null and t.id <> 1000)
You can get these with a little piece of special logic:
select (case when t.previd is null then 1
else t.id + 1
end) as missingid,
(case when t.previd is null then t.id - 1
else (coalesce(t.nextid, 1000) - t.id - 1)
end) as nummissing
from (select t.*, lead(t.id) over (order by t.id) as nextid,
lag(t.id) over (order by t.id) as previd
from table t
where t.id between 1 and 1000 and
) t
where (t.nextid > t.id + 1 or
(t.nextid is null and t.id <> 1000)
(t.previd is null and t.id <> 1)
)
This sounds like one of the many scenarios where it is helpful to have a numbers table:
SELECT *
FROM lkp_Numbers a
WHERE NOT EXISTS (SELECT 1
FROM YourTable b
WHERE a.num = b.Id)
AND num <= 1000
I use this to create a numbers table:
DROP TABLE lkp_Numbers
DECLARE #RunDate datetime
SET #RunDate=GETDATE()
SELECT TOP 1000 IDENTITY(int,1,1) AS Num
INTO lkp_Numbers
FROM sys.objects s1, sys.objects s2, sys.objects s3
ALTER TABLE lkp_Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Num)
That method for creating a numbers table was found here: What is the best way to create and populate a numbers table?
it is possible that similar questions have been asked earlier, but I can't find them. So here is my objective.
I have three tables like 1.Bill 2.BillDetail 3.ExpenseInfo. Table "Bill" have a primary key named "BillID" which is foreign key of table "BillDetail". Similarly, table "ExpenseInfo" have a PK "ExpenseID" which is also FK to "BillDetail". Data kept in these tables are in below format. For 1 entry in Bill table, there might be 1 or more rows in BillDetail table where each row contains 1 ExpenseID. Now I want to write a query which will select data something like-
BillID BillDate Fuel Food Travel
1 28-02-12 10 20 50
here Fuel, Food, Travel are various expense types saved in table "ExpenseInfo". I have tried below. Am I going the right way or some other smart way exists to do this?
SELECT *
FROM t_BillInfoDetail a
LEFT OUTER JOIN
(
SELECT ISNULL(ExpenseID,0) AS ExpenseID, ISNULL(ExpenseName,'N/A') AS ExpenseName
FROM t_expenseinfo
WHERE ExpenseID=1
) AS LocalTravel ON a.ExpenseID = LocalTravel.ExpenseID
Newly Added
Thank you all for your replies.
Currently I am doing as below for my purpose. Hope you like it.
SELECT
BI.* , BID.ExpenseID, BID.BillDescription, BID.LocalTravel, BID.LocalHotel, BID.Fuel
FROM
(
SELECT *
FROM t_BillInfo
WHERE BillID = 1
) AS BI
LEFT OUTER JOIN
(
SELECT BillID, BillDescription, ExpenseID,
ISNULL(SUM(CASE ExpenseID WHEN 1 THEN Amount ELSE 0 END), 0) AS LocalTravel,
ISNULL(SUM(CASE ExpenseID WHEN 2 THEN Amount ELSE 0 END), 0) AS LocalHotel,
ISNULL(SUM(CASE ExpenseID WHEN 3 THEN Amount ELSE 0 END), 0) AS Fuel
FROM t_BillInfoDetail
GROUP BY BillID, BillDescription, ExpenseID
) AS BID ON BI.BillID = BID.BillID
Probably I'm not getting the question right, but as I see it you have 3 tables joined like a "chain" Bill -HAS_MANY> BillDetail -HAS_ONE> ExpenseInfo.
If that is the case you just have to join the tables with inner joins requesting the data from each of the tables you require. You didn't provide your table structure but should be done this way:
select b.aBillField, bd.aBillDetailField, ei.aExpenseInfoField from bill b
inner join billDetail bd
on b.billID = bd.billFK
inner join expenseInfo ei
on ei.expenseFK = bd.billDetailId
where expenseId = 1
Of course, replace the invented fields with the corresponding ones.
In case if u need a store procedure,and if u can be more clear in your question we can easily answer you...for now you try this
create procedure [dbo].[SP_GetInfo]
(
#ExpenseID int
)
as
begin
select Bill .BillID , BillDetail .BillDate , ExpenseInfo.Fuel
from Bill , BillDetail , ExpenseInfo
where Bill .BillID = BillDetail .BillID
AND ExpenseInfo.ExpenseID =#ExpenseID
GO
try this if u have any error please ask me....
If I read correctly, you want to PIVOT your data in the ExpenseInfo table. Try the following:
SELECT BillID,
BillDate,
Fuel,
Food,
Travel
FROM (SELECT BillID,
BillDate,
ExpenseName,
ExpenseAmount
FROM Bill AS B
INNER JOIN BillDetail BD
ON B.BillID = BD.BillID
INNER JOIN ExpenseInfo EI
ON BD.ExpenseID = EI.ExpenseID) AS up PIVOT (SUM( ExpenseAmount
) FOR
ExpenseName IN (Fuel, Food, Travel)) AS pvt
ORDER BY BillID
This is what I am using. It fulfills my requirement.
SELECT
BI.* , BID.ExpenseID, BID.BillDescription, BID.LocalTravel, BID.LocalHotel, BID.Fuel
FROM
(
SELECT *
FROM t_BillInfo
WHERE BillID = 1
) AS BI
LEFT OUTER JOIN
(
SELECT BillID, BillDescription, ExpenseID,
ISNULL(SUM(CASE ExpenseID WHEN 1 THEN Amount ELSE 0 END), 0) AS LocalTravel,
ISNULL(SUM(CASE ExpenseID WHEN 2 THEN Amount ELSE 0 END), 0) AS LocalHotel,
ISNULL(SUM(CASE ExpenseID WHEN 3 THEN Amount ELSE 0 END), 0) AS Fuel
FROM t_BillInfoDetail
GROUP BY BillID, BillDescription, ExpenseID
) AS BID ON BI.BillID = BID.BillID