Monthly Report - SQL - c#

I have the table below, how would I select in SQL the last date of each month (from the list) in each categoryID?
I want to end up with something in the line off:
CategoryID | Current | Date
1 | 5 | 2016-09-30
1 | 3 | 2016-10-30
1 | 7 | 2016-11-30
1 | 2 | 2016-12-30
etc. as history builds up.
Image :

There are a few ways to approaches to do this, one of them could be using windowing function rownumber. Within the CTE (WITH) you get local order of the records within date(using covert to get rid of the time here)+CategoryID partition by datetime DESC (-> first is latest). You need to do this because you cannot use windowing functions in WHERE clause. Then, in the main query, you actually use this CTE as your source table and get only the latest record per partition.
WITH LocallyOrdered AS (
SELECT CategoryID,
StockCurrent,
ROW_NUMBER() OVER (
PARTITION BY CategoryID, CONVERT(date, RecordAdded)
ORDER BY RecordAdded DESC)
AS RowNumberOneIsLatest
FROM OriginalTable)
SELECT CategoryID, StockCurrent FROM LocallyOrdered WHERE RowNumberOneIsLatest = 1

Considering you're using MySQL, since you haven't mentioned.
Suppose this is your table named : 'Dummy'
cat_id current date
------ ------- --------
1 5 2016-09-30
1 3 2016-10-30
1 7 2016-11-30
1 2 2016-12-30
2 4 2016-10-31
2 6 2016-10-04
Executing this query :
select
o.cat_id,
(SELECT DISTINCT
a.date
from
Dummy a
where a.cat_id = o.cat_id
ORDER BY date DESC
LIMIT 1) as 'date'
from
Dummy o
group by o.cat_id ;
Gives you the Latest date of each category :
cat_id date
------ ------------
1 2016-12-30
2 2016-10-31
EDIT
This is supposed to work specifically for your table. Just replace "yourTable" with the table's actual name.
select
o.CategoryID,
o.StockCurrent
(SELECT DISTINCT
a.RecordAdded
from
yourTable a
where a.CategoryID = o.CategoryID
ORDER BY RecordAdded DESC
LIMIT 1) as 'RecordAdded'
from
yourTable o
group by o.CategoryID ;
EDIT 2 :
This Query returns the latest date of each month within a certain category. Hope this is what you want.
SELECT
o.CategoryID,
o.StockCurrent,
o.RecordAdded
FROM
`yourTable` o
WHERE o.RecordAdded IN
(SELECT
MAX(i.RecordAdded)
FROM
`yourTable` i
GROUP BY MONTH(i.RecordAdded))
GROUP BY o.CategoryID,
o.RecordAdded ;
Suppose the table contains the following sample data:
CategoryID StockCurrent RecordAdded
---------- ------------ -------------
1 5 2016-09-01
1 3 2016-09-02
1 7 2016-10-01
1 2 2016-10-02
2 4 2016-09-01
2 6 2016-09-02
2 66 2016-10-01
2 77 2016-10-02
Running this query returns the following result set :
CategoryID StockCurrent RecordAdded
---------- ------------ -------------
1 3 2016-09-02
1 2 2016-10-02
2 6 2016-09-02
2 77 2016-10-02

try this:
WITH Temp As
(
select CategoryId, [Current], RecordAdded,
Dense_Rank() over( partition by CategoryId order by RecordAdded desc) as CatergoryWiseRank
from tblCategory
)
select CategoryId, [Current], RecordAdded from Temp where CatergoryWiseRank=1

SELECT
CASE MONTH(date_field)
WHEN 1 THEN 'Enero'
WHEN 2 THEN 'Febrero'
WHEN 3 THEN 'Marzo'
WHEN 4 THEN 'Abril'
WHEN 5 THEN 'Mayo'
WHEN 6 THEN 'Junio'
WHEN 7 THEN 'Julio'
WHEN 8 THEN 'Agosto'
WHEN 9 THEN 'Septiembre'
WHEN 10 THEN 'Octubre'
WHEN 11 THEN 'Noviembre'
WHEN 12 THEN 'Diciembre'
END as Mes, COUNT(date_field) as cantidad FROM nacimientos
WHERE YEAR(date_field)='1991'
GROUP BY MONTH(date_field)asc
Result

Related

Remove need for second T-SQL query

I am loading some data into a repeater which is coming from two tables. The query against the second table is only selecting the MAX record though, and because of this complexity, I'm having to create a child repeater to then go off and find the Max record to display.
Table A: Activity List
ID | Activity
----+-----------------------
1 | Change Oil Filter
2 | Change brake fluid
3 | Change brake rotors
Table B: Mechanics Log
ID | ActivityID | Date | Mechanic | Comment
---+-------------+-------------+-------------------------------------------
1 | 1 | 2019-27-06 | John | Changed the oil filter
2 | 1 | 2019-26-06 | Sally | No oil filters in stock.
3 | 2 | 2019-20-06 | Sally | Brake fluid flushed.
As stated above, I can produce the following table using two repeaters (one inside the other) and it looks like this.
ActivityID | Date | Mechanic | Comment
-------------+-------------+-----------------------------------------
1 | 2019-27-06 | John | Changed the oil filter
2 | 2019-20-06 | Sally | Brake fluid flushed.
3 | | |
My question is: How can I produce the same table but using only one repeater and 1 T-SQL query? Is it possible? The reason being is that this is a very simple list (shortened for this demonstration) of the full list I have to enable for my mechanics work log, and when i start going to 100+ activities that can be done on a vehicle, the page loads quite slow; assuming because it has to fire off the 2nd repeater + code for each record it has bound.
I also apologize I do not yet have a 'starting point' for you to work with, as nothing I have created has come even close to producing the result in one query. I am having trouble working out how I combine the first part of the query with the MAX(Date) of the 2nd table. Hoping for some assistance from the community to help.
You can use the below query to get the desired result -
Sample Data
Declare #ActivityList Table
(ID int, Activity varchar(100))
Insert into #ActivityList
values
(1 , 'Change Oil Filter' ),
(2 , 'Change brake fluid' ),
(3 , 'Change brake rotors' )
Declare #MechanicsLog Table
(ID int, ActivityID int, [Date] Date, Mechanic varchar(20), Comment varchar(50))
Insert into #MechanicsLog
values
(1 , 1 , '2019-06-27' , 'John' , 'Changed the oil filter' ),
(2 , 1 , '2019-06-26' , 'Sally' , 'No oil filters in stock.' ),
(3 , 2 , '2019-06-20' , 'Sally' , 'Brake fluid flushed.' )
Query
;With cte as
(select ActivityID, Max([Date]) [date] from #MechanicsLog ml
Group By ActivityID
)
Select al.ID, al.Activity, cte.[Date], Mechanic, Comment
from cte inner join #MechanicsLog ml
on cte.ActivityID = ml.ActivityID and cte.[date] = ml.[Date]
right join #ActivityList al on al.ID = ml.ActivityID
order by ID
If you add use the ROW_NUMBER function to add a sequence to each activity ID, you can then filter that to only get the most recent for each activity ID.
select ActivityID, Date, Mechanic, Comment
from
(
select *, ROW_NUMBER() OVER (PARTITION BY ActivityID order by Date desc) RowNumber
from MechanicsLog
) q1
where RowNumber = 1
This gives you the "MAX" record for each ActivityID but with the rest of the record, so you can join to the Activity List table if you want.
select
act.ActivityID, Max(log.[Date]) as [Date]
from
ActivityList act
inner join
MachineLog log on log.ActivityID = act.ActivityID
Group by
act.ActivityID

How to select multiple Row and multiple field by one code with SQL

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

Subtracting 2 columns from different tables with the same ID

I have 2 tables TblAddToInventory and TblWithdrawnFromInventory. Both have ProductID and Quantity. When a withdrawal is made, naturally the Inventory should deduct the quantity of items but only items that have been withdrawn. Example:
TblAddToInventory
ProductID | Quantity | Amount | Date
1 2 2.00 7/7/2012
2 3 3.00 7/7/2012
3 4 4.00 7/7/2012
2 2 2.00 7/8/2012
3 3 3.00 7/8/2012
TblWithdrawnFromInventory
ProductID | Quantity | Amount | Date
2 4 4.00 7/9/2012
3 5 5.00 7/10/2012
With this, when I join the two tables and deduct the specific columns, I should have a DataGridView using C# with this data:
ProductID | Quantity | Amount
1 2 2.00
2 1 1.00
3 2 2.00
I know how to use SUM and JOIN but I just don't know how to create a syntax that will subtract two columns from different tables with the same ID.
I don't know if this is the right way but what I have in mind is SUM all from TblAddToInventory using GROUP BY then SUM all from TblWithdrawnFromInventory using GROUP BY and then SUBTRACT columns from TblAddToInventory and TblWithdrawnFromInventory using GROUP BY. But I don't think that's a good idea. Can you help?
Thank you.
I know how to use SUM and JOIN but I just don't know how to create a
syntax that will subtract two columns from different tables with the
same ID.
This is code how you to do this:
SELECT inventory.ProductId,
inventory.Quantity - ISNULL(withdrawal.Quantity,0) AS Quantity,
inventory.Amount - ISNULL(withdrawal.Amount,0) AS Amount
FROM (
SELECT ProductId, SUM(Quantity) AS Quantity, SUM(Amount) AS Amount
FROM TblAddToInventory
GROUP BY ProductId
) AS inventory
LEFT JOIN (
SELECT ProductId, SUM(Quantity) AS Quantity, SUM(Amount) AS Amount
FROM TblWithdrawnFromInventory
GROUP BY ProductId
) AS withdrawal ON inventory.ProductId = withdrawal.ProductId
Preparation:
-- create temp table with the data, cast the first row's date to set the proper data type
select * into #tblAddToInventory from (
select 1 as ProductID, 2 as Quantity, 2.00 as Amount, cast('7/7/2012' as date) as [Date]
union all select 2 as ProductID, 3 as Quantity, 3.00 as Amount, '7/7/2012' as Date
union all select 3 as ProductID, 4 as Quantity, 4.00 as Amount, '7/7/2012' as Date
union all select 2 as ProductID, 2 as Quantity, 2.00 as Amount, '7/8/2012' as Date
union all select 3 as ProductID, 3 as Quantity, 3.00 as Amount, '7/8/2012' as Date
) a
-- create temp table with the data, cast the first row's date to set the proper data type
select * into #tblWithdrawnFromInventory from (
select 2 as ProductID, 4 as Quantity, 4.00 as Amount, cast('7/9/2012' as date) as [Date]
union all select 3 as ProductID, 5 as Quantity, 5.00 as Amount, '7/10/2012' as Date
) b
-- verify the data looks correct
select * from #tblAddToInventory
-- ProductID Quantity Amount Date
-- ----------- ----------- ----------- ----------
-- 1 2 2.00 2012-07-07
-- 2 3 3.00 2012-07-07
-- 3 4 4.00 2012-07-07
-- 2 2 2.00 2012-07-08
-- 3 3 3.00 2012-07-08
-- verify the data looks correct
select * from #tblWithdrawnFromInventory
-- ProductID Quantity Amount Date
-- ----------- ----------- ----------- ----------
-- 2 4 4.00 2012-07-09
-- 3 5 5.00 2012-07-10
Begin solution:
-- use Union All to join the queries, and multiply the second query by -1 to make them negative
select * from #tblAddToInventory union all
select ProductID, (Quantity * -1) as Quantity, Amount, Date from #tblWithdrawnFromInventory
-- ProductID Quantity Amount Date
-- ----------- ----------- ----------- ----------
-- 1 2 2.00 2012-07-07
-- 2 3 3.00 2012-07-07
-- 3 4 4.00 2012-07-07
-- 2 2 2.00 2012-07-08
-- 3 3 3.00 2012-07-08
-- 2 -4 4.00 2012-07-09
-- 3 -5 5.00 2012-07-10
select ProductID, sum(Quantity) as Quantity, sum(Amount) as Amount from (
select * from #tblAddToInventory union all
select ProductID, (Quantity * -1) as Quantity, (Amount * -1) as Amount, Date from #tblWithdrawnFromInventory
) joinedData
where [Date] >= '7/6/2012' and [Date] <= '7/11/2012'
group by ProductID
-- ProductID Quantity Amount
-- ----------- ----------- -----------
-- 1 2 2.00
-- 2 1 1.00
-- 3 2 2.00
-- delete temp tables
drop table #tblAddToInventory
drop table #tblWithdrawnFromInventory

MySQL - Extract records present in a table but not in another

I know this question has already been asked many times.
The problem is that other solutions don't work..
I tried the following:
SELECT ID FROM TABLE_1 AS T1 WHERE NOT EXISTS (SELECT COLUMN_1,COLUMN_2 FROM TABLE_2 AS T2 WHERE T1.COLUMN_1 = T2.COLUMNS_1 AND T1.COLUMN_2 = T2.COLUMN_2);
It always go in timeout, both from Workbench and from code (I am using Visual Studio 2013 C#).
I don't know how to make the query easier in order to make it work.. Maybe split it in 2..
Example:
Table 1 Table 2
ID COLUMN_1 COLUMN_2 ID COLUMN_1 COLUMN_2
1 0 1 1 0 1
2 0 1 2 0 1
3 0 1 3 0 1
4 1 2
5 1 2
6 1 2
It should return
1 2
Or also only the ID (2).
SELECT
Table_1.ID
,Table_1.COLUMN_1
,Table_1.COLUMN_2
FROM Table_1
LEFT JOIN Table_2
ON Table_1.ID = Table_2.ID
AND Table_1.COLUMN_1 = Table_2.COLUMN_1
AND Table_1.COLUMN_2 = Table_2.COLUMN_2
WHERE Table_2.ID IS NULL
Edit:
Well, if you don't need to match the id, then it's simply:
SELECT
Table_1.ID
,Table_1.COLUMN_1
,Table_1.COLUMN_2
FROM Table_1
LEFT JOIN Table_2
ON Table_2.COLUMN_1 = Table_1.COLUMN_1
AND Table_2.COLUMN_2 = Table_1.COLUMN_2
WHERE Table_2.ID IS NULL
If that's still too slow, maybe an index can help.
If an index doesn't help, you can still increase the command timeout.
Still, another option would be:
SELECT
Table_1.ID
,Table_1.COLUMN_1
,Table_1.COLUMN_2
FROM Table_1
WHERE
(COLUMN_1, COLUMN_2) NOT IN (SELECT COLUMN_1, COLUMN_2 FROM Table_2)

SQL query to get the sum and the latest enries

I have a table called machineStatus:
ID Successfiles totaldata Backupsessiontime
> 1 3 988 1256637314
> 2 21 323 1256551419
> 3 8 23 1256642968
> 4 94 424 1256642968
> 1 42 324 1256810937
> 1 0 433 1256642968
Now here i want to group by ID where the successfiles and total data gets summed up, but only display the latest Backupsessiontime.
I can do this seperately but not together.
Any suggestions????
For doing this seperately:
to get the sum:
select ID, sum(NumOfSuccessFiles), sum(TotalData)
from MachineStat
group by ID;
to get latest:
With idT as (
select ID
from MachineStat
group by ID
)
select applyT.*
from idT p
CROSS APPLY (
select top 1 ID,BackupSessionTime from MachineStat where eID=p.ID
order by MachineID desc
) as applyT
It looks like you want to do
select ID, sum(NumOfSuccessFiles), sum(TotalData), max(Backupsessiontime)
from MachineStat
group by ID;
You can use an aggregate function that would suit your needs:
select
ID,
sum(NumOfSuccessFiles) TotalNumOfSuccessFiles,
sum(TotalData) TotalData,
max(Backupsessiontime) LastBackupsessiontime
from
MachineStat ms
group by
ID
Or you can use a sub-query in your primary query, if you need more complicated sorting logic.
select
ID,
sum(NumOfSuccessFiles) TotalNumOfSuccessFiles,
sum(TotalData) TotalData,
(select top 1 Backupsessiontime from MachineStat where ID = ms.ID order by ...) LastBackupsessiontime
from
MachineStat ms
group by
ID
Max(BackupSessionTime) ?

Categories