calculating number of weeks in the basis of customized weekend - c#

Different organizations might have a different week off.
So, in this case, need to customize the week off. To do it I have tried the
Sql query write in below
DECLARE #dayName VARCHAR(9);
SET #dayName = DATEName(DW, GETDATE());
IF(#dayName = 'Friday' OR #dayName = 'Saturday')
PRINT 'Weekend';
ELSE
PRINT 'NOT Weekend';
From the above query I can get my specific weekoff.
for example:
if friday or any other day is mentioned as weekend, then from friday to Thursday corresponds to a week and I need to find how many complete weeks are there in a month? Or in a year?
I want to get number of weeks on the basis of customized weekOff.

first, you need to make calendar full year or full month, so I would use cte recursion to make it.
SELECT DATEADD(month, DATEDIFF(month, 0, getdate()), 0) AS StartOfMonth,
DATEADD(mm,1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) - 1 AS EndOfMonth
UNION ALL
SELECT StartOfMonth +1 , EndOfMonth
FROM CTE
WHERE StartOfMonth < EndOfMonth
there is 7 days in a week, whatever started with any week, then we will saw this a Gaps and Islands problem, because the week number will repeat from 1to 7.
So I would use CASE WHEN with DateNameto make your customer week date number, which number starts onFriday` or depending on your logic.
;WITH CTE AS (
SELECT DATEADD(month, DATEDIFF(month, 0, getdate()), 0) AS StartOfMonth,
DATEADD(mm,1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) - 1 AS EndOfMonth
UNION ALL
SELECT StartOfMonth +1 , EndOfMonth
FROM CTE
WHERE StartOfMonth < EndOfMonth
)
SELECT *,
CASE DateName(DW, StartOfMonth)
WHEN 'Friday' THEN 0
WHEN 'Saturday' THEN 1
WHEN 'Sunday' THEN 2
WHEN 'Monday' THEN 3
WHEN 'Tuesday' THEN 4
WHEN 'Wednesday' THEN 5
WHEN 'Thursday' THEN 6
WHEN 'Tuesday' THEN 7
END grp,
ROW_NUMBER() OVER(ORDER BY StartOfMonth) rn
FROM CTE
[Results]:
| StartOfMonth | EndOfMonth | grp | rn |
|----------------------|----------------------|-----|----|
| 2018-09-01T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 1 |
| 2018-09-02T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 2 |
| 2018-09-03T00:00:00Z | 2018-09-30T00:00:00Z | 3 | 3 |
| 2018-09-04T00:00:00Z | 2018-09-30T00:00:00Z | 4 | 4 |
| 2018-09-05T00:00:00Z | 2018-09-30T00:00:00Z | 5 | 5 |
| 2018-09-06T00:00:00Z | 2018-09-30T00:00:00Z | 6 | 6 |
| 2018-09-07T00:00:00Z | 2018-09-30T00:00:00Z | 0 | 7 |
| 2018-09-08T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 8 |
| 2018-09-09T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 9 |
| 2018-09-10T00:00:00Z | 2018-09-30T00:00:00Z | 3 | 10 |
| 2018-09-11T00:00:00Z | 2018-09-30T00:00:00Z | 4 | 11 |
| 2018-09-12T00:00:00Z | 2018-09-30T00:00:00Z | 5 | 12 |
| 2018-09-13T00:00:00Z | 2018-09-30T00:00:00Z | 6 | 13 |
| 2018-09-14T00:00:00Z | 2018-09-30T00:00:00Z | 0 | 14 |
| 2018-09-15T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 15 |
| 2018-09-16T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 16 |
| 2018-09-17T00:00:00Z | 2018-09-30T00:00:00Z | 3 | 17 |
| 2018-09-18T00:00:00Z | 2018-09-30T00:00:00Z | 4 | 18 |
| 2018-09-19T00:00:00Z | 2018-09-30T00:00:00Z | 5 | 19 |
| 2018-09-20T00:00:00Z | 2018-09-30T00:00:00Z | 6 | 20 |
| 2018-09-21T00:00:00Z | 2018-09-30T00:00:00Z | 0 | 21 |
| 2018-09-22T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 22 |
| 2018-09-23T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 23 |
| 2018-09-24T00:00:00Z | 2018-09-30T00:00:00Z | 3 | 24 |
| 2018-09-25T00:00:00Z | 2018-09-30T00:00:00Z | 4 | 25 |
| 2018-09-26T00:00:00Z | 2018-09-30T00:00:00Z | 5 | 26 |
| 2018-09-27T00:00:00Z | 2018-09-30T00:00:00Z | 6 | 27 |
| 2018-09-28T00:00:00Z | 2018-09-30T00:00:00Z | 0 | 28 |
| 2018-09-29T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 29 |
| 2018-09-30T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 30 |
then we can try to use rn - grp to get the group, which is continuous.
[Results]:
| StartOfMonth | EndOfMonth | grp |
|----------------------|----------------------|-----|
| 2018-09-01T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-02T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-03T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-04T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-05T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-06T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-07T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-08T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-09T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-10T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-11T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-12T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-13T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-14T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-15T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-16T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-17T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-18T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-19T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-20T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-21T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-22T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-23T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-24T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-25T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-26T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-27T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-28T00:00:00Z | 2018-09-30T00:00:00Z | 28 |
| 2018-09-29T00:00:00Z | 2018-09-30T00:00:00Z | 28 |
| 2018-09-30T00:00:00Z | 2018-09-30T00:00:00Z | 28 |
final, we just get all count(*) = 7 group in month or year number, which mean complete weeks.
Query 1:
full month
;WITH CTE AS (
SELECT DATEADD(month, DATEDIFF(month, 0, getdate()), 0) AS StartOfMonth,
DATEADD(mm,1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) - 1 AS EndOfMonth
UNION ALL
SELECT StartOfMonth +1 , EndOfMonth
FROM CTE
WHERE StartOfMonth < EndOfMonth
)
SELECT COUNT(*) fullweekAmount from (
SELECT
MIN(StartOfMonth) startdt,
MAX(StartOfMonth) enddt
FROM (
SELECT *,
ROW_NUMBER() OVER(ORDER BY StartOfMonth) -
CASE DateName(DW, StartOfMonth)
WHEN 'Friday' THEN 0
WHEN 'Saturday' THEN 1
WHEN 'Sunday' THEN 2
WHEN 'Monday' THEN 3
WHEN 'Tuesday' THEN 4
WHEN 'Wednesday' THEN 5
WHEN 'Thursday' THEN 6
WHEN 'Tuesday' THEN 7
END grp
FROM CTE
) t1
GROUP BY grp
having count(*) = 7
) t1
Results:
| fullweekAmount |
|----------------|
| 3 |
full year
;WITH CTE AS (
SELECT DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0) AS StartOfMonth,
DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) + 1, -1) - 1 AS EndOfMonth
UNION ALL
SELECT StartOfMonth +1 , EndOfMonth
FROM CTE
WHERE StartOfMonth < EndOfMonth
)
SELECT COUNT(*) fullweekAmount from (
SELECT
MIN(StartOfMonth) startdt,
MAX(StartOfMonth) enddt
FROM (
SELECT *,
ROW_NUMBER() OVER(ORDER BY StartOfMonth) -
CASE DateName(DW, StartOfMonth)
WHEN 'Friday' THEN 0
WHEN 'Saturday' THEN 1
WHEN 'Sunday' THEN 2
WHEN 'Monday' THEN 3
WHEN 'Tuesday' THEN 4
WHEN 'Wednesday' THEN 5
WHEN 'Thursday' THEN 6
WHEN 'Tuesday' THEN 7
END grp
FROM CTE
) t1
GROUP BY grp
having count(*) = 7
) t1
option (maxrecursion 0)
sqlfiddle
Note
if your cte recursion date more than 100 you will get the error
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.
you can set
option (maxrecursion 0)
The Case When number 0 and 1 mean your weekoff day

The alternative solution,
DECLARE #StartDate DATE='20200722'--any valid date as your requirement needs(it is inclusive of the specified date)
DECLARE #MonthorYear CHAR='Y'--Valid inputs: 'M'->for month and 'Y'-> for year
DECLARE #WeekdayBeginning nVarchar(15)='Sunday'
----Valid inputs run the following query, in my case it is english, for you it may differ based on your language
--SELECT DATENAME(dw, DATEADD(d,-1,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,0,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,1,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,2,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,3,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,4,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,5,'20180903'))
DECLARE #week TABLE
(ID int identity(0,1),DoW nVarchar(15),isWeekstart bit default 0)
INSERT INTO #week (DoW)
SELECT DATENAME(dw, DATEADD(d,-1,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,0,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,1,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,2,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,3,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,4,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,5,'20180903'))
-- input validations
if not exists (SELECT 1 FROM #week where DoW=#WeekdayBeginning)
BEGIN
PRINT 'Invalid #WeekdayBeginning input'
RETURN
END
if (#MonthorYear NOT IN ('M','Y'))
BEGIN
PRINT 'Invalid #MonthorYear input'
RETURN
END
--Start of find logic
DECLARE #EndDate date
DECLARE #DaysMissed tinyint,#TempDays smallint,#Weeks tinyint
SELECT #EndDate=
case #MonthorYear WHEN 'M' THEN EOMONTH(#StartDate)
ELSE DATEFROMPARTS(YEAR(#StartDate),12,31) END
UPDATE #week set isWeekstart=1 where Dow=#WeekdayBeginning
SELECT #TempDays=DATEDIFF(d,#StartDate,#EndDate)+1
if not exists(SELECT 1 FROM #week WHERE DATENAME(dw,#StartDate)=DoW and isWeekstart=1)
BEGIN
DECLARE #tempID tinyint,#WeekstartID tinyint
SELECT #tempID=ID from #week WHERE DATENAME(dw,#StartDate)=DoW
SELECT #WeekstartID=ID from #week WHERE isWeekstart=1
WHILE(#WeekstartID<>#tempID)
BEGIN
SET #TempDays=#TempDays-1
SET #tempID=#tempID+1
if(#tempID>6)
BEGIN
SET #tempID=0
END
END
END
SET #Weeks=#TempDays/7
SELECT #Weeks as 'CompleteWeeks'

Related

How to list the products under each category in sql? side by side

I'm a bit of a beginner in sql and I need your help.
I'm sorry that I don't know if the question is correct.
now the code gives this;
+---------+----------+-------------+------------+
| id | CompanyId| DealId | price |
+---------+----------+-------------+------------+
| 1 | 1 | 1 | 100 |
| 2 | 1 | 2 | 50 |
| 3 | 1 | 3 | 25 |
| 4 | 2 | 1 | 1000 |
| 5 | 2 | 2 | 2000 |
| 6 | 2 | 3 | 2500 |
+---------+----------+-------------+------------+
but this is what i want;
+---------+----------+-------------+------------+------------+--+
| id | companyId| DealName1 | DealName2 | DealName3 | |
+---------+----------+-------------+------------+------------+--+
| 1 | 1 | 100 | 50 | 25 | |
| 2 | 2 | 1000 | 2000 | 2500 | |
| 3 | 3 | value | value | value | |
| 4 | 4 | value | value | value | |
+---------+----------+-------------+------------+------------+--+
select CompanyId
,[1] as DealName1
,[2] as DealName2
,[3] as DealName3
from (select CompanyId, DealId, price from t) t
pivot (sum(price) for DealId in([1],[2],[3])) p
CompanyId
DealName1
DealName2
DealName3
1
100
50
25
2
1000
2000
2500
Fiddle

How to select closest date from today using Entity Framework?

I have a MySQL database like this
Id Name StartTime
1 test1 2021-02-21 08:15:00
2 test2 2021-02-11 18:00:00
3 test3 2021-02-24 14:00:00
4 test4 2021-02-10 10:30:00
5 test5 2021-02-23 09:00:00
6 test6 2021-02-26 16:00:00
7 test7 2021-02-23 12:00:00
8 test8 2021-02-15 17:00:00
I want to get 5 closest date from today (2021-02-20).
I expected a result like this :
2021-02-26
2021-02-24
2021-02-23
2021-02-21
2021-02-15
I tried with this code :
var result = _context.EventItems
.FromSqlRaw("Select * from Event ORDER BY ABS(`StartTime` - CURRENT_TIMESTAMP()) LIMIT 5")
.Select(e => e.StartTime.Date)
.ToList();
and the result is :
2021-02-24
2021-02-23
2021-02-23
2021-02-21
2021-02-15
The problem is the duplicate 2021-02-23. How can I do to resolve my problem? Thank you !!
Consider the following; I've used '12:00:00' (as opposed to '00:00:00') as the comparison time because it seems more intuitive to me that the 24th is closer to the 20th than the 15th is.
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,name VARCHAR(12) NOT NULL UNIQUE
,start_time DATETIME NOT NULL
);
INSERT INTO my_table VALUES
(1,'test1','2021-02-21 08:15:00'),
(2,'test2','2021-02-11 18:00:00'),
(3,'test3','2021-02-24 14:00:00'),
(4,'test4','2021-02-10 10:30:00'),
(5,'test5','2021-02-23 09:00:00'),
(6,'test6','2021-02-26 16:00:00'),
(7,'test7','2021-02-23 12:00:00'),
(8,'test8','2021-02-15 17:00:00');
SELECT *
, SEC_TO_TIME(ABS(UNIX_TIMESTAMP(start_time)-UNIX_TIMESTAMP('2021-02-20 12:00:00')))x
FROM my_table
ORDER
BY x ;
+----+-------+---------------------+-----------+
| id | name | start_time | x |
+----+-------+---------------------+-----------+
| 1 | test1 | 2021-02-21 08:15:00 | 20:15:00 |
| 5 | test5 | 2021-02-23 09:00:00 | 69:00:00 |
| 7 | test7 | 2021-02-23 12:00:00 | 72:00:00 |
| 3 | test3 | 2021-02-24 14:00:00 | 98:00:00 |
| 8 | test8 | 2021-02-15 17:00:00 | 115:00:00 |
| 6 | test6 | 2021-02-26 16:00:00 | 148:00:00 |
| 2 | test2 | 2021-02-11 18:00:00 | 210:00:00 |
| 4 | test4 | 2021-02-10 10:30:00 | 241:30:00 |
+----+-------+---------------------+-----------+

How to update stock table quantity on the basis of expiry date?

Hello everyone i have a table of inventory stock with columns as following
Item_ID | Expiry_Date | Quantity | Rate
cB0001 | 01-18-2021 | 5 | 150
cB0001 | 12-08-2020 | 3 | 145
cB0001 | 02-15-2021 | 25 | 155
Note : Rate is not an issue I just want to update the Stock Table Quantity on the basis on expiry date and available qty.
Now i want to sale inventory to customers of item cB0001 qty : 10 from the stock that expire first. Now the problem is that sale quantity is 10 and I want to minus the quantity 5 of expiry date 01-18-2021 and 3 From expiry date 12-08-2020 and 2 from 02-15-2021. Basically i want to implement FIFO logic using one query. I want to update the stock table quantity using this
update stock set quantity = quantity - '10' where item_id = 'cB0001' and expiry_Date < Now()
But this not giving accurate result. How to fix this problem? you have any idea?
I hope you understand my question
I assume you intend to do this in a trigger. So the 'trick' is to work out when the sale is fulfilled (working out IF it can be fulfilled is another issue). To do this allocate a value of 0 to rows where the cumulative quantity is less than the sale, 1 to the row where the sale can finally be fullfilled and 2 after that. I have assumed there is a unique row identifier to cope with multiple inventory entries for the same date - in my case inventory.id
drop table if exists inventory,sales;
create table inventory
(id int auto_increment primary key,Item_ID varchar(20), Expiry_Date date, Quantity int, Rate int);
create table sales (item_id varchar(20), quantity int);
insert into inventory values
( null,'cB0001' , str_to_date('01-18-2021','%m-%d-%Y'), 5 , 150),
( null,'cB0001' , str_to_date('12-08-2020','%m-%d-%Y'), 3 , 145),
( null,'cB0001' , str_to_date('02-15-2021','%m-%d-%Y'), 25 , 155),
( null,'cB0001' , str_to_date('02-15-2021','%m-%d-%Y'), 10 , 155),
( null,'cB0001' , str_to_date('02-15-2021','%m-%d-%Y'), 10 , 155),
( null,'cB0001' , str_to_date('02-15-2021','%m-%d-%Y'), 10 , 155),
( null,'cB0002' , str_to_date('02-15-2021','%m-%d-%Y'), 30 , 155);
drop trigger if exists t;
delimiter $$
create trigger t after insert on sales
for each row
begin
update inventory left join
(select s.*,
if(fst = 0, #runqty:=#runqty+quantity,#runqty:=#runqty) qty
from
(
select *,
#t:=#t+quantity cumqty,
if(#t>=#sale,if(#p>=1,2,#p:=1),#p:=0) fst
from inventory
cross join (select #t:=0,#p:=0,#sale:=new.quantity) t
where quantity > 0 and item_id = new.item_id
order by item_id,expiry_date
) s
cross join (select #runqty:=0) r
where fst in (0,1)
) a
on a.id = inventory.id
set inventory.quantity = case when fst = 0 then 0
when fst = 1 then inventory.quantity - (new.quantity - a.qty)
else inventory.quantity
end;
end $$
delimiter ;
MariaDB [sandbox]> insert into sales values('cb0001',10);
Query OK, 1 row affected (0.095 sec)
MariaDB [sandbox]> select * from inventory order by item_id,expiry_date;
+----+---------+-------------+----------+------+
| id | Item_ID | Expiry_Date | Quantity | Rate |
+----+---------+-------------+----------+------+
| 2 | cB0001 | 2020-12-08 | 0 | 145 |
| 1 | cB0001 | 2021-01-18 | 0 | 150 |
| 3 | cB0001 | 2021-02-15 | 23 | 155 |
| 4 | cB0001 | 2021-02-15 | 10 | 155 |
| 5 | cB0001 | 2021-02-15 | 10 | 155 |
| 6 | cB0001 | 2021-02-15 | 10 | 155 |
| 7 | cB0002 | 2021-02-15 | 30 | 155 |
+----+---------+-------------+----------+------+
7 rows in set (0.001 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> insert into sales values('cb0001',25);
Query OK, 1 row affected (0.111 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from inventory order by item_id,expiry_date;
+----+---------+-------------+----------+------+
| id | Item_ID | Expiry_Date | Quantity | Rate |
+----+---------+-------------+----------+------+
| 2 | cB0001 | 2020-12-08 | 0 | 145 |
| 1 | cB0001 | 2021-01-18 | 0 | 150 |
| 3 | cB0001 | 2021-02-15 | 0 | 155 |
| 4 | cB0001 | 2021-02-15 | 8 | 155 |
| 5 | cB0001 | 2021-02-15 | 10 | 155 |
| 6 | cB0001 | 2021-02-15 | 10 | 155 |
| 7 | cB0002 | 2021-02-15 | 30 | 155 |
+----+---------+-------------+----------+------+
7 rows in set (0.001 sec)

How to solve null value in MySQL?

I want to show data separately from income and expense table in MySQL using same query for both things but it show me when show income title date then same show expense title date. But I need to do if it find income table's 4th row and if find expense table's 2nd row, but it show me 4th row. Why?
SELECT income.date,
IF(income.income_sourch IS NULL, 'N/A', income.income_sourch )as 'Income Title',
income.amount as 'income',
IF(expense.expense_sourche IS NULL, 'N/A', expense.expense_sourche) as 'ExpenseTitle',
expense.amount as 'Expense'
from expense RIGHT JOIN income
ON expense.date=income.date
where expense.date='30-Aug-2016'
Why - because that's how joins work when you have only a date to join the 2 tables. To solve this you need to create a relationship in addition to the date bearing in mind that at any one time the number of records in income could be greater than, less than or equal to the number of records in expenses. If we generate a row number for each row in income and independently generate a row number for each row in expenses then we can join income and expenses on row number
for example
/*
CREATE TABLE INCOME (ID INT,DESCRIPTION VARCHAR(10),DT DATE,AMOUNT INT);
INSERT INTO INCOME VALUES
(1,'SALE','2016-08-30',100),
(2,'ROKY','2016-08-30',200),
(3,'KORIM','2016-08-30',300),
(4,'SALEVOUCHR','2016-08-30',400);
CREATE TABLE EXPENSES (ID INT,DESCRIPTION VARCHAR(10),DT DATE,AMOUNT INT);
TRUNCATE TABLE EXPENSES;
INSERT INTO EXPENSES VALUES
(1,'RENT','2016-08-30',100),
(2,'UTILITIES','2016-08-30',100);
/*
This code
SELECT S.DT,S.DESCRIPTION,S.AMOUNT, s.rn,T.DESCRIPTION,T.AMOUNT, t.rn1
FROM
(
SELECT I.DT,I.DESCRIPTION,I.AMOUNT,
#RN:=#RN + 1 RN
FROM (SELECT #RN:=0) RN,INCOME I
) S
LEFT OUTER JOIN
(SELECT E.DT,E.DESCRIPTION,E.AMOUNT,
#RN1:=#RN1 + 1 RN1
FROM (SELECT #RN1:=0) RN1, EXPENSES E
) T ON T.RN1 = S.RN AND T.DT = S.DT
WHERE S.DT IS NOT NULL
results in
+------------+-------------+--------+------+-------------+--------+------+
| DT | DESCRIPTION | AMOUNT | rn | DESCRIPTION | AMOUNT | rn1 |
+------------+-------------+--------+------+-------------+--------+------+
| 2016-08-30 | SALE | 100 | 1 | RENT | 100 | 1 |
| 2016-08-30 | ROKY | 200 | 2 | UTILITIES | 100 | 2 |
| 2016-08-30 | KORIM | 300 | 3 | NULL | NULL | NULL |
| 2016-08-30 | SALEVOUCHR | 400 | 4 | NULL | NULL | NULL |
+------------+-------------+--------+------+-------------+--------+------+
BUT this is UNSAFE because it assumes that there are always more income than expense items
for example if we add 3 more expense rows
TRUNCATE TABLE EXPENSES;
INSERT INTO EXPENSES VALUES
(1,'RENT','2016-08-30',100),
(2,'UTILITIES','2016-08-30',100),
(3,'RATES','2016-08-30',100),(4,'SALARY','2016-08-30',100),(5,'INSURANCE','2016-08-30',100);
then the last expense item is lost resulting in
+------------+-------------+--------+------+-------------+--------+------+
| DT | DESCRIPTION | AMOUNT | rn | DESCRIPTION | AMOUNT | rn1 |
+------------+-------------+--------+------+-------------+--------+------+
| 2016-08-30 | SALE | 100 | 1 | RENT | 100 | 1 |
| 2016-08-30 | ROKY | 200 | 2 | UTILITIES | 100 | 2 |
| 2016-08-30 | KORIM | 300 | 3 | RENT | 100 | 3 |
| 2016-08-30 | SALEVOUCHR | 400 | 4 | UTILITIES | 100 | 4 |
+------------+-------------+--------+------+-------------+--------+------+
To cope with this we can simulate a full join like so
SELECT S.*,T.*
FROM
(
SELECT I.DT,I.DESCRIPTION,I.AMOUNT,
#RN:=#RN + 1 RN
FROM (SELECT #RN:=0) RN,INCOME I
) S
LEFT JOIN
(SELECT E.DT,E.DESCRIPTION,E.AMOUNT,
#RN1:=#RN1 + 1 RN1
FROM (SELECT #RN1:=0) RN1, EXPENSES E
) T ON T.RN1 = S.RN AND T.DT = S.DT
UNION
SELECT S.*,T.*
FROM
(
SELECT I.DT,I.DESCRIPTION,I.AMOUNT,
#RN3:=#RN3 + 1 RN3
FROM (SELECT #RN3:=0) RN3,INCOME I
) S
RIGHT JOIN
(SELECT E.DT,E.DESCRIPTION,E.AMOUNT,
#RN4:=#RN4 + 1 RN4
FROM (SELECT #RN4:=0) RN4, EXPENSES E
) T ON T.RN4 = S.RN3 AND T.DT = S.DT
result
+------------+-------------+--------+------+------------+-------------+--------+------+
| DT | DESCRIPTION | AMOUNT | RN | DT | DESCRIPTION | AMOUNT | RN1 |
+------------+-------------+--------+------+------------+-------------+--------+------+
| 2016-08-30 | SALE | 100 | 1 | 2016-08-30 | RENT | 100 | 1 |
| 2016-08-30 | ROKY | 200 | 2 | 2016-08-30 | UTILITIES | 100 | 2 |
| 2016-08-30 | KORIM | 300 | 3 | 2016-08-30 | RATES | 100 | 3 |
| 2016-08-30 | SALEVOUCHR | 400 | 4 | 2016-08-30 | SALARY | 100 | 4 |
| NULL | NULL | NULL | NULL | 2016-08-30 | INSURANCE | 100 | 5 |
+------------+-------------+--------+------+------------+-------------+--------+------+
you just need to add limits inside the query
if expense table limit 2
if other limit 4
See how to add limit to the query with if condition

Table listing the comparison of each record in other table

I want to create a table listing the comparison of each record in a table with every other record on basis of particular columns :
Example :
id | web | author | book | isbn | pub
----------------------------------------------------------------
1 | www.a.com | sam | sams book | 12345 | sams pub
2 | www.b.com | ram | rams book | 54321 | rams pub
3 | www.c.com | sam | rams book | 67891 | tams pub
4 | www.b.com | ram | gams book | 65644 | gams pub
5 | www.a.com | sam | sams book | 11111 | xyzs pub
6 | www.c.com | tam | tams book | 22222 | abcs pub
7 | www.c.com | tam | tams book | 33333 | pqrs pub
So I want to create table with the comparision result of each record with every other record
on columns web,author,book
Result Table should be : (result weight is addition of web+author+book weight)
sorceRow|destRow| web | author | book | result weight
--------------------------------------------------------
1 | 2 | 0 | 0 | 0 | 0
1 | 3 | 0 | 1 | 0 | 1
1 | 4 | 0 | 0 | 0 | 0
1 | 5 | 1 | 1 | 1 | 3
1 | 6 | 0 | 0 | 0 | 0
1 | 7 | 0 | 0 | 0 | 0
2 | 3 | 0 | 0 | 1 | 1
2 | 4 | 1 | 1 | 0 | 2
2 | 5 | 0 | 0 | 0 | 0
2 | 6 | 0 | 0 | 0 | 0
...
6 | 7 | 1 | 1 | 1 | 3
What is fastest way to get this result in SQL Server script as well as in C#?
You can do this with a non-equijoin and lots of comparisons. The following is the standard SQL method:
select t1.id as sourceRow, t2.id as destRow,
(case when t1.web = t2.web then 1 else 0 end) as Web,
(case when t1.Author = t2.Author then 1 else 0 end) as Author,
(case when t1.Book = t2.Book then 1 else 0 end) as Book,
(case when t1.ISBN = t2.ISBN then 1 else 0 end) as ISBN,
(case when t1.pub = t2.pub then 1 else 0 end) as pub
from table t1 join
table t2
on t1.id < t2.id;
Note that the comparisons would be a little more complicated if the columns could contain NULL values, but your sample data doesn't have any.
Basically CROSS JOIN of the table on itself will do that multiplication Cross Join.
As for comparison, it depends on the DB server you use - case or iif().
select
l.id as sourceRow,
r.id as destRow,
iif (r.web = l.web, 1, 0) as web,
iif (r.author = l.author, 1, 0) as author,
....
from T1 l
cross join T1 r
where l.id < r.id

Categories