Convert Query in Mysal to SQL? - sql

I am using Entity Framework i got a error '"The query syntax is not valid. Near term ':', line 1, column 109." from system .data.entity.sqlserver. so please tell me to convert below query in SQL
SELECT Agentid,year(Date_Time) as Year,monthname(Date_Time) as Month,SUM(AmountRecevied) as Amount,#rownum := #rownum + 1 AS Rank FROM collection_master,
(SELECT #rownum := 0) r GROUP BY AgentID,year(Date_Time),monthname(Date_Time) ORDER BY
Amount DESC
Agentid logintime AmountReceived
1 2013/10/01 00:10:10 10000
1 2013/10/01 17:23:10 200
1 2013/10/01 00:30:41 3000
2 2013/10/02 05:10:52 1000
3 2013/10/02 09:10:25 2000
3 2013/10/03 10:10:18 2000
2 2013/10/03 13:10:35 7000
I want a query that should display the output as
Agentid Amount Rank
1 13200 1
2 8000 2
3 4000 3
I had Tried below query not getting expected output please check it once
with temp as (
select row_number() over (order by AmountRecevied) as rownum,AgentID,YEAR(Date_Time) as Years,SUM(AmountRecevied) as amount
from tblcollections group by CustomerID,AgentID,Date_Time ,AmountRecevied
select rownum,AgentID,Years,amount from temp

This should do the job: I cant test it, so pls give it a try.
WITH CTE AS
(
SELECT Agentid,year(Date_Time) as Year, MONTH(Date_Time) as Month,SUM(AmountRecevied) as Amount
FROM collection_master,
GROUP BY AgentID,year(Date_Time),MONTH(Date_Time)
)
SELECT *, ROW_NUMBER() OVER (ORDER BY CTE.Amount DESC) AS RANKING
FROM CTE
Order by RANKING

Related

SQL - Returning unique row based on criteria and a priority

I have a data table that looks in practice like this:
Team Shirt Number Name
1 1 Seaman
1 13 Lucas
2 1 Bosnic
2 14 Schmidt
2 23 Woods
3 13 Tubilandu
3 14 Lev
3 15 Martin
I want to remove duplicates of team by the following logic - if there is a "1" shirt number, use that. If not, look for a 13. If not look for 14 then any.
I realise it is probably quite basic but I don't seem to be making any progress with case statements. I know it's something with sub-queries and case statements but I'm struggling and any help gratefully received!
Using SSMS.
Since you didn't specified any DBMS, let me assume row_number() would work for that :
DELETE
FROM (SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY Team
ORDER BY (CASE WHEN Shirt_Number = 1
THEN 1
WHEN Shirt_Number = 13
THEN 2
WHEN Shirt_Number = 14
THEN 3
ELSE 4
END)
) AS Seq
FROM table t
) t
WHERE Seq = 1;
This assuming Shirt_Numbers have a gap else only order by Shirt_Number enough.
I think you are looking for a partition by clause usage. Solution below worked in Sql Server.
create table #eray
(team int, shirtnumber int, name varchar(200))
insert into #eray values
(1, 1, 'Seaman'),
(1, 13, 'Lucas'),
(2, 1, 'Bosnic'),
(2, 14, 'Schmidt')
;with cte as (
Select Team, ShirtNumber, Name,
ROW_NUMBER() OVER (PARTITION BY Team ORDER BY ShirtNumber ASC) AS rn
From #eray
where ShirtNumber in (1,13,14)
)
select * from cte where rn=1
If you have a table of teams, you can use cross apply:
select ts.*
from teams t cross apply
(select top (1) ts.*
from teamshirts ts
where ts.team = t.team
order by (case shirt_number when 1 then 1 when 13 then 2 when 14 then 3 else 4 end)
) ts;
If you have no numbers between 2 and 12, you can simplify this to:
select ts.*
from teams t cross apply
(select top (1) ts.*
from teamshirts ts
where ts.team = t.team
order by shirt_number
) ts;

how to select multiple max values from column in sql server?

I have following two tables TBLSession and TBLStudentFeeRecord having following sample datasets
TBLSession:
SessionId SessionName SessionStartMonth SessionEndMonth
1 2018-2019 2018-03-24 2019-02-24
2 2019-2020 2019-01-30 2019-12-30
3 2020-2021 2020-01-30 2021-12-30
TBLStudentFeeRecord:
StudentId SessionId TutionFee BranchId ClassId SectionId
1001 1 1000 1 1 1
1001 2 2000 1 3 1
1001 3 1000 2 2 1
Now,what i am trying to achieve is to select two maximum sessions TutionFee of selected StudentId. I can use max(columnName) to get one maximum value from that particular column. Now how can i get two maximum sessions?
Following dataset is required after querying these table
ResultDataSet:
StudentId SessionId TutionFee SessionName
1001 2 2000 2019-2020
1001 3 1000 2020-2021
What will be the query to achieve above dataset?
You can use SQL Row_Number function with Partition By clause if you want to get the 2 session info per student
Otherwise, use Row_number() function without Partition By clause
You can find explanations for two alternatives in the following SQL CTE statements
;with cte as (
select *,
-- top 2 session per student
-- rn = ROW_NUMBER() over (partition by studentid order by sessionid desc)
-- top 2 sessions
rn = ROW_NUMBER() over (order by sessionid desc)
from TBLStudentFeeRecord
)
select
*
from cte
inner join TBLSession on TBLSession.sessionid = cte.sessionid
where rn <= 2
The output is as follows
You can modify the select list according to your requirements
Since you haven't posted your tries, so try something like this:
Pseudo query:
select top 2 from (select TutionFee from TBLStudentFeeRecord
where StudentId = 1001
order by TutionFee desc )
You could use a subselect Top 2 on the max TutionFee and SessionId
select a.* , t.TutionFee
from TBLSession a
inner JOIN (
select TOP 2 studentID, TutionFee, SessionId
from TBLStudentFeeRecord
where StudentId = 1001
order TutionFee desc, SessionID desc
) t on t.SessionId = a.SessionId
Try this:
SELECT StudentId ,SessionId,TutionFee,SessionName
FROM(
SELECT TSF.StudentId ,TSF.SessionId,TSF.TutionFee,TS.SessionName
,ROW_NUMBER() OVER(PARTITION BY TSF.TutionFee ORDER BY SessionId DESC)RN
FROM TBLStudentFeeRecord TSF
INNER JOIN TBLSession TS ON TS.SessionId=TSF.SessionId
)D
WHERE RN=1
this should work
select TBLStudentFeeRecord.StudentId, TBLStudentFeeRecord.SessionId, TBLStudentFeeRecord.TutionFee, TBLStudentFeeRecord.SessionName
from TBLStudentFeeRecord
inner join TBLSession on TBLSession.SessionId = TBLStudentFeeRecord.SessionId
where TBLStudentFeeRecord.StudentId = 1000
ORDER BY TBLStudentFeeRecord.TutionFee DESC
LIMIT 2
In general query languages are powerful if you face any difficult or any complex scenario just use stored procedure
Two max..........................................
CREATE PROCEDURE twoMaxFrom()
BEGIN
DECLARE max1 DOUBLE;
DECLARE max2 DOUBLE;
DECLARE emp_cursor CURSOR FOR SELECT
TutionFee
FROM TBLStudentFeeRecord;
-- 2. Declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
-- 3. Open the cursor
OPEN emp_cursor;
L: LOOP
-- 4. Fetch next element
FETCH emp_cursor
INTO TutionFee;
-- Handler will set finished = 1 if cursor is empty
IF finished = 1
THEN
LEAVE L;
END IF;
SET max1 = 0;
SET max2 = 0;
IF max1 > max2
THEN
SET max1 = TutionFee;
SET max2 = max1;
END IF;
END LOOP;
-- 5. Close cursor when done
CLOSE emp_cursor;
SELECT max1;
SELECT max2;
END;
You can get it by using join and TOP
SELECT TOP 2 StudentId
,t1.SessionId
,TutionFee
,SessionName
FROM TBLSession AS t1
INNER JOIN TBLStudentFeeRecord AS t2 ON t1.SessionId = t2.SessionId
WHERE t2.StudentId = 1001
ORDER BY t1.SessionId DESC

Paging in SQL with no break on primary key

I am new to Stackoverflow. Please forgive me if I have made some mistake.
I have following data in SQL.
Row No. Customer No. Customer Name
------------------------------------------------------------
1 1234 ABCD
2 1234 ABCD
3 1234 ABCD
4 6789 WXYZ
5 6789 WXYZ
6 3456 OPQR
7 4567 JKLM
I need to page the above data with following constraint
Page size : 4 records
If customer no. is splitting between two pages then new customer no. should go on the next page.
output desired:
Paging with 4 records each page
1st Page
Row No. Customer No. Customer Name
------------------------------------------------------------
1 1234 ABCD
2 1234 ABCD
3 1234 ABCD
2nd Page
Row No. Customer No. Customer Name
------------------------------------------------------------
4 6789 WXYZ
5 6789 WXYZ
6 3456 OPQR
7 4567 JKLM
Please help.
You can read page size +1 records using any limiting, then if the last record and the record before the last has the same Customer Name just filter out the customer using HAVING.
Could be tricky and depends on DB you use and could be easily done on presentation layer
Declare #PageNumber INT = 1, #PageSize INT = 4
;with cte1(RowNo,CustomerNo,CustomerName)
AS
(
Select 1,1234,'ABCD' union all
Select 2,1234,'ABCD' union all
Select 3,1234,'ABCD' union all
Select 4,6789,'WXYZ' union all
Select 5,6789,'WXYZ' union all
Select 6,3456,'OPQR' union all
Select 7,4567,'JKLM'
)
select * from cte1 order by RowNo
OFFSET #PageSize * (#PageNumber - 1) ROWS
FETCH NEXT #PageSize ROWS ONLY
This can be done and not to complicated using recursive CTE.
For sample data, I have used query from other answer
WITH cte1(RowNo,CustomerNo,CustomerName)
AS
(
SELECT 1,1234,'ABCD' UNION ALL
SELECT 2,1234,'ABCD' UNION ALL
SELECT 3,1234,'ABCD' UNION ALL
SELECT 4,6789,'WXYZ' UNION ALL
SELECT 5,6789,'WXYZ' UNION ALL
SELECT 6,3456,'OPQR' UNION ALL
SELECT 7,4567,'JKLM'
)
SELECT * INTO #table FROM cte1
I'l add one more row with reapaing user to split this to 3rd page
INSERT #table (RowNo, CustomerNo, CustomerName) VALUES (8,3456,'OPQR')
And here is the solution. I've put some comments to explain parts
WITH CTE_Source AS
(
--I use this to add RN column simply beacuse I can't trust that rowNo column will have no gaps
SELECT *
, ROW_NUMBER() OVER (ORDER BY RowNo) RN
FROM #table t
)
, CTE_R AS
(
--First part is select of first row
SELECT s.RowNo
, s.CustomerNo
, s.CustomerName
, s.RN
, 1 AS Grp --this is a current group of rows
, 1 AS Cnt --counter of how many rows group have
FROM CTE_Source s WHERE RN = 1
UNION ALL
--subsequent select is for next row
SELECT
s.RowNo
, s.CustomerNo
, s.CustomerName
, s.RN
-- increase group when different customer
, CASE WHEN s.CustomerNo = r.CustomerNo THEN r.Grp ELSE r.Grp+Cnt END
-- increase counter when same customer
, CASE WHEN s.CustomerNo = r.CustomerNo THEN r.Cnt + 1 ELSE 1 END
FROM CTE_R r
INNER JOIN CTE_Source s ON s.RN = r.Rn + 1
)
, CTE_Paging AS
(
SELECT *
, CEILING((r.Grp + r.Cnt) / 4.) AS Page -- replace 4 with your page size
FROM CTE_R r
)
SELECT * FROM CTE_Paging --Just add WHERE Page = if you want specific page
OPTION (MAXRECURSION 0) -- for unlimited recursion if you have more than 100 rows

Unable to fetch modify data in select query [duplicate]

This question already has answers here:
Increased amount of each row in sql
(4 answers)
Closed 8 years ago.
I did not get a good answer for my previous question. In this question I provide more thing but still not get proper result.. anyone help me...
1st row amount=1200,
2nd row amount=1320(1200+120),
3rd row amount=1452(1320+132)
Logic is 10% add with previous amount
;WITH nums AS
(SELECT 1 AS RowNum, 1200 AS value
)
SELECT RowNum, Value
FROM nums
Results:
Sno - Name- Amount
1 - A - 1200
Now I want result like this..
Sno - Name- Amount
1 - A - 1200
2 - A - 1320
3 - A - 1452
Can anybody help me I'm not find any logic for that in same query no external table create or implement
I come from Oracle background; but I hope this helps as it works for me in Oracle:
WITH nums(rn, value) AS
(
SELECT ROWNUM rn, 1200 AS value FROM DUAL
UNION ALL
SELECT rn + 1 rn, round(value * 1.1) FROM nums
where rn < 100
)
SELECT RowNum, Value
FROM nums
It generates up to 100 rows.
You need to use Recursive CTE like this :
WITH nums(rn, value) AS
(
SELECT 1 rn, 1200 AS value
UNION ALL
SELECT rn + 1 rn, value + round(value/10,2) as value
FROM nums
where rn < 10
)
SELECT rn, Value
FROM nums
SQL Fiddle Demo

SQL query to select percentage of total

I have a MSSQL table stores that has the following columns in a table:
Storeid, NumEmployees
1 125
2 154
3 10
4 698
5 54
6 98
7 87
8 100
9 58
10 897
Can someone help me with the SQL query to produce the top stores(storeID) that has 30% of the total emplyees(NumEmployees)?
WITH cte
AS (SELECT storeid,
numemployees,
( numemployees * 100 ) / SUM(numemployees) OVER (PARTITION BY 1)
AS
percentofstores
FROM stores)
SELECT *
FROM cte
WHERE percentofstores >= 30
ORDER BY numemployees desc
Working Demo
Alternative that doesn't use SUM/OVER
SELECT s.storeid, s.numemployees
FROM (SELECT SUM(numemployees) AS [tots]
FROM stores) AS t,
stores s
WHERE CAST(numemployees AS DECIMAL(15, 5)) / tots >= .3
ORDER BY s.numemployees desc
Working Demo
Note that in the second version I decided not to multiply by 100 before dividing. This requires a cast to decimal otherwise it would be implicitly converted to a int resulting in no records returned
Also I'm not completely clear that you want this, but you can add TOP 1 to both queries and it will limit the results to just the one with the greatest # of stores with more than 30%
UPDATE
Based on your comments it sounds to paraphrase Kevin
You want the rows, starting at the store with the most employees and working down until you have at least 30 %
This is difficult because it requires a running percentage and its a bin packing problem however this does work. Note I've included two other test cases (where the percent exactly equals and its just over the top two combined)
Working Demo
DECLARE #percent DECIMAL (20, 16)
SET #percent = 0.3
--Other test values
--SET #percent = 0.6992547128452433
--SET #percent = 0.6992547128452434
;WITH sums
AS (SELECT DISTINCT s.storeid,
s.numemployees,
s.numemployees + Coalesce(SUM(s2.numemployees) OVER (
PARTITION
BY
s.numemployees), 0)
runningsum
FROM stores s
LEFT JOIN stores s2
ON s.numemployees < s2.numemployees),
percents
AS (SELECT storeid,
numemployees,
runningsum,
CAST(runningsum AS DECIMAL(15, 5)) / tots.total
running_percent,
Row_number() OVER (ORDER BY runningsum, storeid ) rn
FROM sums,
(SELECT SUM(numemployees) total
FROM stores) AS tots)
SELECT p.storeID,
p.numemployees,
p.running_percent,
p.running_percent,
p.rn
FROM percents p
CROSS JOIN (SELECT MAX(rn) rn
FROM percents
WHERE running_percent = #percent) exactpercent
LEFT JOIN (SELECT MAX(rn) rn
FROM percents
WHERE running_percent <= #percent) underpercent
ON p.rn <= underpercent.rn
OR ( exactpercent.rn IS NULL
AND p.rn <= underpercent.rn + 1 )
WHERE
underpercent.rn is not null or p.rn = 1