I am new to T-sql .
I am using the following Query:
SELECT e.Id,e.cAvg,
CASE
WHEN e.cAvg<=0.8 and cAvg>=0 THEN t.Model when t.Cr='0.8' then t.Model
WHEN e.cAvg>0.8 and cAvg<=5.4 THEN t.Model WHEN t.Cr='5.4' then t.Model
WHEN e.cAvg>5.4 and cg<=8 THEN t.Model WHEN t.Cr='8' then t.Model
ELSE 'No Change Required'
END
from A e, B t;
What I am trying to do is:
Select id and cAvg columns in Table A.
Compare cAvg in Table A with Cr in Table B.
Use the comparison in CASE to select the particular row which satisfies the condition.
Use the selected row to give query results.
t.Model is a column of table B. I want to select t.Model value of the selected row in the case statement.
I feel the way is to somehow include a equivalent of the where clause inside When of CASE.
Need Direction!!
The table schema:
Table A:
+----+------+
| id | cAvg |
+----+------+
| 1 | .8 |
| 2 | 5.4 |
| 3 | 6.0 |
+----+------+
Table B:
+-----+-------+
| Cr | Model |
+-----+-------+
| 2 | M1 |
| 5.5 | M2 |
| 8 | M3 |
+-----+-------+
I want to the following:
Compare the values of cAvg with a condition => (cAvg<=8 And cAvg>=5.5 => the model selected must be M3.)
The result I want to get is:
+----+------+-------+
| id | cAvg | Model |
+----+------+-------+
| 1 | .8 | M1 |
| 2 | 5.4 | M2 |
| 3 | 6.0 | M3 |
+----+------+-------+
I tired Join as suggested in the comments, A great thanks , I learnt a lot because of it!!.
My problem is that there are no common columns to join.
Also I need to compare the column in one table with that of another table and then give a result based on the comparison.
I referred to many answers in stack overflow but all the answers are for the premise where there is a common column.
I tried the following:
Inner Join
Cases
I need a direction as to which direction I need to go into.
Thank you!!
1st of all, you're selecting from 2 tables but without any link restrictions, so all rows are compared
If there is a matching key between the tables, so only relevant pairs of rows would be compared, it should be used, in a JOIN statement:
A e JOIN B t ON e.id = t.id
2nd of all, in order to select relevant lines, you should decide what these are..
you can inside a WHERE statement define whatvare the relent cases
WHERE
e.cAvg > 12
You can use the case statement inside WHERE but then the result should be conditioned are returned TRUE
SELECT e.Id,e.cAvg, t.Model
A e JOIN B t ON e.id = t.id
WHERE
CASE WHEN e.cAvg<=6 THEN t.Model when t.Cr=6 then t.Model
WHEN e.cAvg>6 and e.cAvg<=12 THEN t.Model
WHEN t.Cr='12' then t.Model
WHEN e.cAvg>12 and cg<=24 THEN t.Model
WHEN t.Cr='24' then t.Model
ELSE -1 END ! = -1
EDIT
Following you question edit, I think that what you need is a JOIN with a condition
Basically, instead of joining the tables with an equal key, join them with an unequal key.
Since you're looking for cAvg BETWEEN to t. Cr rows, 2 JOINs are needed
SELECT e.Id,e.cAvg, t.Model
FROM
A e JOIN B t ON
e.cAvg >= t.Cr
JOIN B t2 ON
e.cAvg < t2.Cr
WHERE
t.Cr IS NOT NULL
AND t2.Cr IS NOT NULL
The idea is that only where the 2 conditions are met, you would get the results of e
Hope that helps
I found a possible work around for the problem.
Problem Statement:
Compare two tables with no common column.
Use the comparison in CASE to select a particular row.
A WHERE Clause inside CASE is not accepted in T-SQL.
My Work Around :
Add a new column in the second table.
Assign An id from Table B to the column in Table A.
Use the assigned id to select the required row in Table B.
Tables:
Table A:
+----+------+
| id | cAvg |
+----+------+
| 1 | .8 |
| 2 | 5.4 |
| 3 | 6.0 |
+----+------+
Table B
+-----+-----+-------+
| Bid | Cr | Model |
+-----+-----+-------+
| 1 | 2 | M1 |
| 2 | 5.5 | M2 |
| 3 | 8 | M3 |
+-----+-----+-------+
Query to assign id's:
CREATE VIEW [AssignIDView] AS
SELECT DISTINCT e.id,
e.cAvg,
(CASE
WHEN e.cAvg>=0 and e.cAvg<=2 THEN 1
WHEN e.cAvg>2 and e.cAvg<=5.5 THEN 2
WHEN e.cAvg>3 and e.cAvg<=8 THEN 3
ELSE 'Invalid'
END) As BId
FROM A e, B t;
The result of the above Query will be a view as follows:
+----+------+-----+
| id | cAvg | Bid |
+----+------+-----+
| 1 | .8 | 1 |
| 2 | 5.4 | 2 |
| 3 | 6.0 | 3 |
+----+------+-----+
Now use Bid to select rows from table B to assign Model from B:
Query:
CREATE VIEW [ModelAssignView] AS
select e.id,
e.cAvg,
t.Model as [Model]
FROM A e, B t where e.TierID = t.id;
The result of the Query will be as follows:
+----+------+-------+
| id | cAvg | Model |
+----+------+-------+
| 1 | .8 | M1 |
| 2 | 5.4 | M2 |
| 3 | 6.0 | M3 |
+----+------+-------+
The intention of my question was to do the above.
For that I wanted to find an Equivalent of A WHERE Clause inside CASE.
But the above method achieved the solution for me.
Hope it helps:)!
Related
Say I have two tables: A and B
Table A
+----+-------+
| id | value |
+----+-------+
| 1 | 20 |
| 2 | 20 |
| 3 | 10 |
| 4 | 0 |
+----+-------+
Table B
+----+-------+
| id | value |
+----+-------+
| 1 | 20 |
| 2 | 10 |
| 3 | 30 |
| 4 | 20 |
| 5 | 20 |
| 6 | 10 |
+----+-------+
If I do SELECT value, COUNT(*) AS occurrence FROM A GROUP BY value, I'll get:
+-------+------------+
| value | occurrence |
+-------+------------+
| 20 | 2 |
| 10 | 1 |
| 0 | 1 |
+-------+------------+
Based on this grouping of table A, I want to delete occurrence records from table B with the same values. In other words, I want to delete from B 2 records with value 20, 1 record with value 10, and 1 record with value 0. (Other conditions include 'do nothing if no record exists' and 'smallest id first', but I think these conditions are pretty trivial compared to the bulk of this question.)
Table B after deleting should be:
+----+-------+
| id | value |
+----+-------+
| 3 | 30 |
| 5 | 20 |
| 6 | 10 |
+----+-------+
From the official TOP documentation, doesn't seems like I can perform some JOIN to use as the TOP expression.
We could use ROW_NUMBER with CTEs here:
WITH cteA AS (
SELECT value, COUNT(*) cnt
FROM A
GROUP BY value
),
cteB AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY value ORDER BY id) rn
FROM B
)
DELETE
FROM cteB b
INNER JOIN cteA a
ON b.value = a.value
WHERE
b.rn <= a.cnt;
The logic here is that we use ROW_NUMBER to keep track of the order of each value in the B table. Then, we join to bring in the counts of each value in the A table, and we only delete B records for which the row number is strictly less than or equal to the A count.
See the demo link below to verify that the logic be correct. Note that I use a select there, not a delete, but the correct rows are being targeted for deletion.
Demo
I have two tables in SQL Server, Say in table1 I have two columns Key1Display and Key2Display, they are of datatype bit and used to control whether to display the values in table2, and table 2 will have 2 columns Key1 and Key2.
What I am trying to achieve is a sort of cross join, say if table 1 has 3 rows:
| Key1Display | Key2Display |
+---------------------+------------------+
| 0 | 1 |
| 1 | 0 |
| 1 | 1 |
Say in table 2 there are 2 rows
| Key1 | Key2 |
+---------------------+------------------+
| Row1Key1value | Row1Key2value |
| Row2Key1value | Row2Key2value |
Then based on these two tables, I want to have a query to display 6 (2*3) rows and 1 column of results like this:
null:Row1Key2value
Row1Key1Value:null
Row1Key1Value:Row1Key2value
null:Row2Key2value
Row1Key2Value:null
Row1Key2Value:Row2Key2value
So something like:
select
case when t1.Key1Display = 1 then coalesce(t2.Key1,'??') else 'null' end
+ ':' + case when t1.Key2Display = 1 then coalesce(t2.Key2,'??') else 'null' end
-- And so on for as many keys as you have
from table1 t1
cross join table2 t2
I have imported two Excel sheets as tables in Microsoft's SQL Server Management Server 2007, and they are both identical, except for the fact that they are from 2 different dates.
I'm looking to do 2 things that I'm struggling to do:
Calculate the monthly difference between values for the 2 tables which I can do with cast, and
inner join, but I'm not successful in using those values to be able to sum those values with a nested case like so:
SELECT SUM(
CASE WHEN ID <>'MISSING' THEN
CASE WHEN SUM(VALUE)>=0 THEN
SUM(VALUE)
ELSE
0
END
END)
I've tried many different ways, but one of the main errors I get is:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
The data would like so:
dbo.Table1
date(dd/mm/yy) | name | id | value
---------------+------+---------+-------
1/1/14 | A | MISSING | 56
1/1/14 | A | MISSING | -1
1/1/14 | B | YES | 56
1/1/14 | B | YES | -1
dbo.Table2
date(dd/mm/yy) | name | id | value
---------------+------+---------+-------
1/2/14 | A | MISSING | 24
1/2/14 | A | MISSING | -11
1/2/14 | B | YES | 24
1/2/14 | B | YES | -11
Don't use SUM inside another SUM, just keep only the outer SUM. Also your outer CASE has no ELSE part, but you'd probably want to have 0 in that scenario as well, so why not use a single CASE condition?
SELECT SUM(CASE WHEN ID <> 'MISSING' AND VALUE >= 0 THEN VALUE ELSE 0 END)
I have this table :
id | type | date
1 | a | 01/1/2012
2 | b | 01/1/2012
3 | b | 01/2/2012
4 | b | 01/3/2012
5 | a | 01/5/2012
6 | b | 01/5/2012
7 | b | 01/9/2012
8 | a | 01/10/2012
The POV is per date. if 2 rows contains the same date , so both will visible in the same line ( left join).
Same date can be shared by 2 rows max.
so this situation can't be :
1 | a | 01/1/2012
2 | b | 01/1/2012
3 | a | 01/1/2012
if in the same date there is group a and b show both of them in single line using left join
if in date there is only a group , show it as single line ( +null at the right side )
if in date there is only b group , show it as single line ( +null at the left side )
Desired result :
Date |typeA|typeB |a'id|b'id
01/1/2012 | a | b | 1 | 2
01/2/2012 | | b | | 3
01/3/2012 | | b | | 4
01/5/2012 | a | b | 5 | 6
01/9/2012 | | b | | 7
01/10/2012 | a | | 8 |
I know this suppose to be simple , but the main anchor of join here is the date.
The problem I've encountered is when I read line 1 , i search in the table all rows with the same date...fine. - its ok.
But when I read the second line , I do it also , and it yields the first row - which already was counted...
any help ?
here is the sql fiddle :
https://data.stackexchange.com/stackoverflow/query/edit/82605
I think you want a pivot
select
[date],
case when [a] IS null then null else 'a' end typea,
case when [b] IS null then null else 'b' end typeb,
a as aid,
b as bid
from yourtable src
pivot (max(id) for type in ([a],[b]))p
If you want to do it with joins..
select ISNULL(a.date, b.date), a.type,b.type, a.id,b.id
from
(select * from yourtable where type='a') a
full outer join
(select * from yourtable where type='b') b
on a.date = b.date
My database is quite complex so I've simplified my problem down to the tables below.
TableA and TableB are related by the NameID field in TableB. I am trying to create a SQL statement to produce the desired results. I'm understand JOINs and how they work but I can't fogure this out.
There will never be more than 2 items in TableB for each item in TableA. There could be less than 2 items.
This will be used on a SQL Server 2000 server.
TableA
ID | Name
---+-----
1 | John
2 | Jane
3 | Bob
4 | Doug
TableB
ID | NameID | Information
---+--------+------------
1 | 1 | Apples
2 | 1 | Apples
3 | 2 | Pears
4 | 2 | Grapes
5 | 3 | Kiwi
Desired Result
ID | Name | InformationA | InformationB
---+------+--------------+-------------
1 | John | Apples | Apples
2 | Jane | Pears | Grapes
3 | Bob | Kiwi | NULL
4 | Doug | NULL | NULL
(Edited to give the preferred ordering for the two columns)
SELECT a.Id,
a.Name,
STUFF(MIN(STR(b.Id, 10) + b.Information), 1, 10, '') AS InformationA,
CASE
WHEN COUNT(b.Id) = 2 THEN STUFF(MAX(STR(b.Id, 10) +
b.Information), 1, 10, '')
END AS InformationB
FROM TableA a
LEFT JOIN TableB b
ON a.Id = b.NameId
GROUP BY a.Id,
a.Name
I think what you need to do is a pivot. Take a look and see if that suits your needs.