Arithmetic operation on row value - sql

I have a table with the below data
Tid Did value
------------------
1 123 100
1 234 200
2 123 323
2 234 233
All tids have dids as 123 and 234. So for every tid having dids 123 and 234 I want to calculate value of did 123/value of did 234 * 100 i.e 100/200 * 100
For tid 2 it will be value of did 123/value of did 234 * 100 i.e 323/233 * 100
The output table will be
Tid result
------------------
1 100/200 * 100
2 323/233 * 100
Any help?

JOIN the "123" rows with the "234" rows:
select t123.tid, t123.value * 100 / t234.value
from
(select tid, value from tablename where value = 123) t123
join
(select tid, value from tablename where value = 234) t234
on t123.tid = t234.tid

JOIN, all in ON
select t123.tid, t123.value * 100 / t234.value
from tablename t123
join tablename t234 on t123.tid = t234.tid and t123.did = 123 and t234.did = 234

Here is the query. We can use inner join to achieve it.
SELECT T1.Tid,(T1.value/T2.value)*100 AS Result
FROM Table_1 AS T1
INNER JOIN
Table_1 AS T2
ON (T1.Tid = T2.Tid)
AND (T1.Did <> T2.Did)
AND T1.Did = 123

select tid,
100 * sum(case when did = 123 then value end) /
sum(case when did = 234 then value end)
from your_table
group by tid
having sum(case when did = 234 then value end) > 0

Related

select data by passing a value in where clause if the value match then return that data otherwise return all data

select data by passing a value in where clause if the value match then return matches data otherwise return all data.
Consider following example
ID Name
1 ABC
2 DEF
3 GHI
4 JKL
When pass id = 1 the return row 1 when pass null value or 0 then return all data.
You can use analytical function as follows:
SELECT * FROM
(SELECT T.*,
SUM(CASE WHEN T.ID = <YOUR_VALUE(0,1,NULL, or any)> THEN 1 ELSE 0 END) OVER () AS SM
FROM YOUR_TABLE T)
WHERE SM = 0 OR ID = <YOUR_VALUE(0,1,NULL, or any)>
You need to replace <YOUR_VALUE(0,1,NULL)> with a value that you want to pass.
For values 0 and 1, results are as follows:
SQL> SELECT * FROM
2 (SELECT T.*,
3 SUM(CASE WHEN T.ID = 0 THEN 1 ELSE 0 END) OVER () AS SM
4 FROM YOUR_TABLE T)
5 WHERE SM = 0 OR ID = 0 ;
ID NAM SM
---------- --- ----------
1 ABC 0
2 DEF 0
3 GHI 0
4 JKL 0
SQL>
SQL>
SQL> SELECT * FROM
2 (SELECT T.*,
3 SUM(CASE WHEN T.ID = 1 THEN 1 ELSE 0 END) OVER () AS SM
4 FROM YOUR_TABLE T)
5 WHERE SM = 0 OR ID = 1;
ID NAM SM
---------- --- ----------
1 ABC 1
SQL>
You can use not exists:
select t.*
from t
where id = 1 or
not exists (select 1 from t t2 where t2.id = 1);
Or as a passed-in value:
select t.*
from t
where id = :input or
not exists (select 1 from t t2 where t2.id = :input);
Note that this works for NULL values as well, because the where in the subquery would evaluate to NULL if :input is NULL.

To select data from multiple records in SQL Server having a common ID

I need to select/concat data from 2 tables in SQL Server I'm using Left Join, but the data is returned as multiple records.
Below are the sample tables
Table1
Id Name Age
1 Sk 20
2 Rb 30
Table2
ID Bike Price Table1Id
1 RX 200 1
2 CD 250 1
3 FZ 300 1
4 R1 400 2
The desired output is
ID Name Age Bike1 Price1 Bike2 Price2 Bike3 Price3
1 Sk 20 RX 200 CD 250 FZ 300
2 Rb 30 R1 400 NULL NULL NULL NULL
A sample format of the query I'm using
SELECT A.ID, A.Name, B.Bike, B.Price FROM Table1 A LEFT JOIN Table2 B ON
A.id = B.Table1Id order by A.id
The output I'm getting from the above query is
ID Name Age Bike Price
1 Sk 20 RX 200
1 Sk 20 CD 250
1 Sk 20 FZ 300
2 Rb 30 R1 400
I need the data as one record for a particular ID and not multiple records (As seen in the desired output). Tired using offset, but offset will return only limited result not the entire records.
Any suggestions on how this can be achieved?
If you know the maximum number of bikes per person, you can use conditional aggregation:
SELECT ID, Name,
MAX(CASE WHEN seqnm = 1 THEN Bike END) as bike_1,
MAX(CASE WHEN seqnm = 1 THEN Price END) as price_1,
MAX(CASE WHEN seqnm = 2 THEN Bike END) as bike_2,
MAX(CASE WHEN seqnm = 2 THEN Price END) as price_2,
MAX(CASE WHEN seqnm = 3 THEN Bike END) as bike_3,
MAX(CASE WHEN seqnm = 3 THEN Price END) as price_3
FROM (SELECT A.ID, A.Name, B.Bike, B.Price,
ROW_NUMBER() OVER (PARTITION BY A.id ORDER BY B.Price) as seqnum
FROM Table1 A LEFT JOIN
Table2 B
ON A.id = B.Table1Id
) ab
GROUP BY ID, Name,
ORDER BY id

Customer Dimension

I am writing a SQL code to create a Customer Dimension.
ID Name File Import Date
1 XXX 12/30/2018
1 XXX 12/31/2018
1 XXX 1/1/2019
1 YYY 2/2/2019
1 YYY 3/2/2019
1 YYY 4/2/2019
2 AAA 1/1/2019
I want to create a Query where I can capture the distinct Name along with the History
New table
ID Name Active
1 XXX 0
1 YYY 1
2 AAA 1
Below query give me the latest record
SELECT Distinct a.[ID] as CustID
,a.[Name] as CustName
FROM X as a
inner join
(select ID,[MaxDate] = MAX(FileImportDate) from X group by ID ) b
on a.ID = b.ID
and a.FileImportDate = b.MaxDate`
enter code here`
I'll bite...
Going by comments, this is a guess
Example
Select Top 1 with ties
ID
,Name
,Active = case when [FileImportDate] = max([FileImportDate]) over (Partition By ID) then 1 else 0 end
From YourTable
Order By Row_Number() over (Partition By Name Order by [FileImportDate] Desc)
Returns
ID Name Active
2 AAA 1
1 XXX 0
1 YYY 1
Here is a dbFiddle
With distinct and case:
select
distinct t.id, t.name,
case
when exists (
select 1 from tablename
where
id = t.id
and name <> t.name
and fileimportdate > t.fileimportdate) then 0
else 1
end active
from tablename t
See the demo
Results:
id name active
1 XXX 0
1 YYY 1
2 AAA 1

Select the row based on the specific key

I have a SQL dataset that looks like this:
SourceId SomeContent
-------------------
1 aaa
2 bbb
3 ccc
4 ddd
SourceId ConditionType CondidionValue
-------------------------------
1 1 2
1 2 200
2 1 3
2 2 201
3 1 4
I need to select the SourceId that have matching specific key,
e.g. (ConditionType=1 and ConditionValue=2) and (ConditionType=2 and ConditionValue=200 ) should return sourceId = 1). Query with specified key can match only one SourceId.
I'm trying to do it this way:
SELECT SourceId
FROM ConditionData
where ConditionType = 2 and ConditionValue = 200
and SourceId in(
SELECT SourceId
FROM ConditionData
where (ConditionType = 1 and ConditionValue = 2))
Is there more elegant query to get it?
You could use aggregation:
SELECT SourceId
FROM ConditionData
WHERE (ConditionType = 2 and ConditionValue = 200)
OR (ConditionType = 1 and ConditionValue = 2)
GROUP BY SourceId
HAVING COUNT(1) = 2 -- Alternatively: COUNT(1) > 1
I think you can use INNER JOIN for each condition
SELECT DISTINCT t1.SourceId
FROM table1 AS t1
INNER JOIN table2 AS condition1 ON t1.SourceId = condition1.SourceId AND condition1.ConditionType = 1 AND condition1.CondidionValue = 2
INNER JOIN table2 AS condition2 ON t1.SourceId = condition2.SourceId AND condition2.ConditionType = 2 AND condition2.CondidionValue = 200

Retrieve matching rows using join

This is a simplified version of my problem.
I have table like below
Id Name SNumber
100 XYZ 123
100 XYZ 123
101 ABC 123
103 QAZ 123
100 XYZ 971
100 XYZ 872
100 XYZ 659
102 PQR 145
102 PQR 707
103 QAZ 421
I want to count rows having Snumber as '123' ie Total column and rows having Snumber not as '123' i.e. otherTotal column
Id Name Total OtherTotal
100 XYZ 2 3
101 ABC 1 0
102 PQR 0 2
103 QAZ 1 1
What I am doing is using join
Select xx.*,otherTotal
From
( Select Id,Name,count(*) as Total
From table
Where Snumber like '123'
Group By id,name
)xx
Inner join
( Select Id,Name,count(*) as otherTotal
From table
Where Snumber not like '123'
Group By id,name
)yy
On xx.Id=yy.Id
But this will only return rows if particular Id has both Snumber as 123 and not as 123
Data returned is like below
Id Name Total OtherTotal
100 XYZ 2 3
103 QAZ 1 1
Now there is no guarntee that a particular Id will always have Snumber as 123 so I can't use Left or Right join. How to solve this quagmire ? Giggity
Try this:
SELECT id, name,
COUNT(CASE WHEN SNumber = 123 THEN 1 END) Total,
COUNT(CASE WHEN SNumber <> 123 THEN 1 END) OtherTotal
FROM t
GROUP BY id, name
ORDER BY id
Fiddle here.
select
Id, Name,
sum(case when SNumber = 123 then 1 else 0 end) as Total,
sum(case when SNumber <> 123 then 1 else 0 end) as OtherTotal
from Table1
group by Id, Name
order by Id
or
select
Id, Name,
count(*) - count(nullif(SNumber, 123)) as Total,
count(nullif(SNumber, 123)) as OtherTotal
from Table1
group by Id, Name
order by Id
sql fiddle demo
try this one.
DECLARE #TABLE TABLE (ID INT, NAME VARCHAR(40), SNUMBER INT)
INSERT INTO #TABLE
VALUES
(100 ,'XYZ', 123),
(100 ,'XYZ', 123),
(101 ,'ABC', 123),
(103 ,'QAZ', 123),
(100 ,'XYZ', 971),
(100 ,'XYZ', 872),
(100 ,'XYZ', 659),
(102 ,'PQR', 145),
(102 ,'PQR', 707),
(103 ,'QAZ', 421)
SELECT
ID,
NAME,
(
SELECT
COUNT(SNUMBER) FROM #TABLE B
WHERE
SNUMBER = '123' AND A.ID = B.ID
) AS TOTAL,
(
SELECT
COUNT(SNUMBER) FROM #TABLE B
WHERE
SNUMBER <> '123' AND A.ID = B.ID
) AS OTHERTOTAL
FROM
#TABLE A
GROUP BY ID, NAME