Sql 2000 data format using a group by query - sql-server

There is a table with below mentioned sample data.I need to get a result set in a specific format.
Original table
org type value
a 1 1000
a 2 200
b 1 1020
b 2 100
c 1 890
c 2 20
Required Result set
org value
a (1000-2000)/1000
b (1020-100)/1020
c (890-20)/890
How to achieve this using SQL 2000.Do I ahve to pivot to get the org wise values as shown above?

No
select t1.org, (t1.value - t2.value) / t1.value
From myTable t1
inner join myTable t2 on t1.org = t2.org and t1.type = 1 and t2.type = 2
should do it, given there's always a type 1 and type 2 for each org

CREATE TABLE #tmp (
Org VARCHAR(50)
,[type] INT
,value DECIMAL(18, 2)
)
INSERT #tmp (Org,[type],value)
VALUES ('a',1,1000)
,('a',2,200)
,('b',1,1020)
,('b',2,100)
,('c',1,890)
,('c',2,20)
SELECT t1.Org
,(t1.Value-t2.value) / t1.Value [Math Done]
,'('+convert(varchar(10),t1.Value) +'-'
+ convert(varchar(10),t2.Value)+')/'
+convert(varchar(10),t1.Value) [Math Shown]
FROM (SELECT Org, Value FROM #tmp WHERE Type = 1) t1
INNER JOIN (SELECT Org, Value FROM #tmp WHERE Type = 2) t2
ON t1.Org = t2.Org
DROP TABLE #tmp
Results:
Org Math Done Math Shown
a 0.8000000000000000000 (1000.00-200.00)/1000.00
b 0.9019607843137254901 (1020.00-100.00)/1020.00
c 0.9775280898876404494 (890.00-20.00)/890.00
Working example, if you want to display the math instead of just doing it.

Related

All records of the same table reladed by a field but queried by anothe field - sqlserver

DB: SQLSERVER
i've this table:
id-description-code
1 -fdsdfsf -A
2 -ghggh -A
3 -tytytyty -B
4 -hjhjydx -A
i need a query that "filtering on one id" ("2" for example) returns me all record of the same table relate by "code"
look for id=2 the result should be:
1 -fdsdfsf -A
2 -ghggh -A
4 -hjhjydx -A
i wrote these two query that works:
SELECT * FROM TABLE S2 INNER JOIN
(select * from TABLE
WHERE ID=2) S1
ON S1.CODE=S2.CODE
SELECT * FROM TABLE S2
WHERE S2.CODE IN (SELECT CODE FROM TABLE S1 WHERE ID =2)
could you give me others example of query (with different operators, for example CROSS APPLY, EXIST or others) to get the same result
This seems to be a strange request just looking for possible ways of returning the same information. But you seem to have skipped the easiest way. Notice how I am posting consumable data so others can just write a query? You should do this in the future.
declare #Something table
(
ID int
, description varchar(20)
, CODE char(1)
)
insert #Something values
(1, 'fdsdfsf', 'A')
,(2, 'ghggh', 'A')
,(3, 'tytytyty', 'B')
,(4, 'hjhjydx', 'A')
select *
from #Something s
join #Something s2 on s2.CODE = s.CODE
where s.ID = 2
Or using CROSS APPLY
select *
from #Something s
cross apply (select * from #Something s2 where s2.CODE = s.CODE) x
where s.ID = 2
Why make it any more complicated than it needs to be?
select * from sometable where code =
(select code from sometable where id=2)

How to check for a specific condition by looping through every record in SQL Server?

I do have following table
ID Name
1 Jagan Mohan Reddy868
2 Jagan Mohan Reddy869
3 Jagan Mohan Reddy
Name column size is VARCHAR(55).
Now for some other task we need to take only 10 varchar length i.e. VARCHAR(10).
My requirement is to check that after taking the only 10 bits length of Name column value for eg if i take Name value of ID 1 i.e. Jagan Mohan Reddy868 by SUBSTRING(Name, 0,11) if it equals with another row value. here in this case the final value of SUBSTRING(Jagan Mohan Reddy868, 0,11) is equal to Name value of ID 3 row whose Name is 'Jagan Mohan Reddy'. I need to make a list of those kind rows. Can somebody help me out on how can i achieve in SQL Server.
My main check is that the truncated values of my Name column should not match with any non truncated values of Name column. If so i need to get those records.
Assuming I understand the question, I think you are looking for something like this:
Create and populate sample data (Please save us this step in your future questions)
DECLARE #T as TABLE
(
Id int identity(1,1),
Name varchar(15)
)
INSERT INTO #T VALUES
('Hi, I am Zohar.'),
('Hi, I am Peled.'),
('Hi, I am Z'),
('I''m Zohar peled')
Use a cte with a self inner join to get the list of ids that match the first 10 chars:
;WITH cte as
(
SELECT T2.Id As Id1, T1.Id As Id2
FROM #T T1
INNER JOIN #T T2 ON LEFT(T1.Name, 10) = t2.Name AND T1.Id <> T2.Id
)
Select the records from the original table, inner joined with a union of the Id1 and Id2 from the cte:
SELECT T.Id, Name
FROM #T T
INNER JOIN
(
SELECT Id1 As Id
FROM CTE
UNION
SELECT Id2
FROM CTE
) U ON T.Id = U.Id
Results:
Id Name
----------- ---------------
1 Hi, I am Zohar.
3 Hi, I am Z
Try this
SELECT Id,Name
FROM(
SELECT *,ROW_NUMBER() OVER(PARTITION BY Name, LEFT(Name,11) ORDER BY ID) RN
FROM Tbale1 T
) Tmp
WHERE Tmp.RN = 1
loop over your column for all the values and put your substring() function inside this loop and I think in Sql index of string starts from 1 instead of 0. If you pass your string to charindex() like this
CHARINDEX('Y', 'Your String')
thus you will come to know whether it is starting from 0 or 1
and you can save your substring value as value of other column with length 10
I hope it will help you..
I think this should cover all the cases you are looking for.
-- Create Table
DECLARE #T as TABLE
(
Id int identity(1,1),
Name varchar(55)
)
-- Create Data
INSERT INTO #T VALUES
('Jagan Mohan Reddy868'),
('Jagan Mohan Reddy869'),
('Jagan Mohan Reddy'),
('Mohan Reddy'),
('Mohan Reddy123551'),
('Mohan R')
-- Get Matching Items
select *, SUBSTRING(name, 0, 11) as ShorterName
from #T
where SUBSTRING(name, 0, 11) in
(
-- get all shortnames with a count > 1
select SUBSTRING(name, 0, 11) as ShortName
from #T
group by SUBSTRING(name, 0, 11)
having COUNT(*) > 1
)
order by Name, LEN(Name)

T-SQL: Remove 1 row out of 2 rows where the value of 1 column is double that of the second

Given the following 2 rows of data:-
ColumnA ColumnB ColumnC ColumnD
33 10298 11588 4474.32
33 10298 11588 2237.16
How do I go about writing a T-SQL query which will remove only the first data row where ColumnsA - C are the same and the value in ColumnD is double that of the second data row.
It doesn't have to particularly performant as I am only removing approximately 500 rows.
Something along these lines should work:
DELETE FROM t2
FROM table t1
inner join
table t2
on
t1.ColumnA = t2.ColumnA and
t1.ColumnB = t2.ColumnB and
t1.ColumnC = t2.ColumnC and
t1.ColumnD * 2 = t2.ColumnD
This assumes that if you have 3 rows where their ratios between columnD values are 1 : 2 : 4, you want to delete both the 2 and 4 rows. If that's not the case, please consider such a situation and let me know what should happen there.
DELETE documentation
Complete script:
create table T (A int,B int, C int, D int)
insert into T(A,B,C,D)
values (1,2,3,4),(1,2,3,8)
delete from t2
from t t1
inner join
t t2
on
t1.A = t2.A and t1.B = t2.B and t1.C = t2.C and t1.D * 2 = t2.D
select * from T
Result:
A B C D
----------- ----------- ----------- -----------
1 2 3 4
Try this solution:
delete from YourTable
from YourTable t1
where exists (select 1 from YourTable t2 where t1.ColumnA=t2.ColumnA and t1.ColumnB=t2.ColumnB and t1.ColumnC=t2.ColumnC and t1.ColumnD=t2.ColumnD*2)
You can't use the same table two times in a join statement, if You want delete from that table. So use istead the join an exists statement or join a derived table.

How can I update by one UPDATE statement in SQL server for the following scenario?

How can I update by one UPDATE statement for the following scenario?
I have 2 tables. The TableA contains the following fields:
TestNumber, CO, CO2, N20, CH4
and the value of TestNumber column is 1, 2, 3
TableA
TestNumber CO CO2 N2O CH4
1
2
3
The second table named TableB contains the following fields:
TestNumber, TestIdentifier, TestValue
and the values are the below:
TableB
TestNumber TestIdentifier TestValue
1 CO 12.3
1 CO2 10
2 CO 9.8
2 N20 45
3 CO 12.5
3 CO2 13.0
I’M EXPECTING THE RESULT AS:
TestNumber CO CO2 N2O CH4
1 12.3 10
2 9.8 45
3 12.5 13.0
I did it using a chunk of code like, declare table variable. Then store data from TableB to the table variable. Then SET rowCount =1 then looping and deleting one row and update the TableA which work perfect. I got my expected result. But I believe I can do direct UPDATE command without too many table variables declaration and looping. I’m updating though but not directly.
I want to learn how I can update directly without looping.
Reply to:
Try this :
You can use PIVOT to convert the TableB in the same form as TableA having TestIdentifier as the column names for the TableB
Select TestNumber ,[Co],[CO2],[N2O],[CH4]
FROM
( Select TestNumber,TestIdentifier,TestValue from TableB) as sourceTable
pivot
(
sum(TestValue)
for TestIdentifier in ([Co],[CO2],[N2O],[CH4])
)
as pvt
Now you can simply use inner join on TestNumber and update the TableA
Update t
set t.Co=cte.CO,
t.CO2=cte.CO2,
t.N2O=cte.N2O,
t.CH4=cte.CH4
from TableA as t
inner join cte
on cte.TestNumber=t.TestNumber
The complete sql query is
;With cte (TestNumber ,[Co],[CO2],[N2O],[CH4])
as
(
Select TestNumber ,[Co],[CO2],[N2O],[CH4]
FROM
( Select TestNumber,TestIdentifier,TestValue from TableB) as sourceTable
pivot
(
sum(TestValue)
for TestIdentifier in ([Co],[CO2],[N2O],[CH4])
)
as pvt
)
Update t
set t.Co=cte.CO,
t.CO2=cte.CO2,
t.N2O=cte.N2O,
t.CH4=cte.CH4
from TableA as t
inner join cte
on cte.TestNumber=t.TestNumber
For complete solution try SQLFIDDLE
You could read something about pivot tables... maybe it helps.
But if your first table is static.. I mean, it's always the same coloumns and the same rows, you could do something like this:
Update tableA set
CO = (Select sum(testValue) from TableB where testNumber = 1 and testIdentifier = 'CO'),
CO2 = (Select sum(testValue) from TableB where testNumber = 1 and testIdentifier = 'CO2'),
N20 = (Select sum(testValue) from TableB where testNumber = 1 and testIdentifier = 'N20'),
CH4 = (Select sum(testValue) from TableB where testNumber = 1 and testIdentifier = 'CH4')
where testNumber = 1
You can write this two more times for the other tests... or if they are variable.. you can write this inside a while loop

How to avoid NULL when using Value-Name Mapping in SQL

I have a table like the following which is basically used to "give a name" to a value in a table (this table contains values for a bunch of other tables as well, not just for MYTABLE; I've omitted a few irrelevant fields from NAMEVALUEMAP):
NAMEVALUEMAP Table
---------------------
VALUE_ | NAME_
---------------------
0 | ZERO
1 | ONE
I didn't want to use JOINs so I thought of using Sub-Queries.
Problem is when a value does not exist in the NAMEVALUEMAP table then NULL is shown.
Instead of NULL I want to show the actual value from MYTABLE (MYTABLE has ID field as identity column and contains a few rows):
-- //Fine, prints word 'ZERO' when MYTABLE.ABC is 0
SELECT
(SELECT NAME_ FROM NAMEVALUEMAP WHERE VALUE_ = (SELECT ABC FROM MYTABLE inner_ WHERE inner_.ID = outer_.ID))
FROM
MYTABLE outer_
-- //Not Fine, prints NULL (because "999" is not in NAMEVALUEMAP). In this case, MYTABLE.ABC is 999
-- //Want it to print 999 if the value is not in NAMEVALUEMAP
SELECT
(SELECT NAME_ FROM NAMEVALUEMAP WHERE VALUE_ = (SELECT ABC FROM MYTABLE inner_ WHERE inner_.ID = outer_.ID))
FROM
MYTABLE outer_
-- //Tried COALESCE, but the error is "Invalid column name 'VALUE_'"
SELECT
COALESCE((SELECT NAME_ FROM NAMEVALUEMAP WHERE VALUE_ = (SELECT ABC FROM MYTABLE inner_ WHERE inner_.ID = outer_.ID)), ABC)
FROM
MYTABLE outer_
Also, is there a better way to do this sort of value-to-name mapping?
I would recomend using a LEFT JOIN (is there any reason you are voidung it?) and ISNULL
SELECT ISNULL(NAME_, ABC)
FROM MYTABLE m LEFT JOIN
NAMEVALUEMAP n ON m.ABC = n.VALUE_
Well, in that case you can try
SELECT ISNULL((select NAME_ FROM NAMEVALUEMAP WHERE VALUE_ = m.ABC), m.ABC)
FROM MYTABLE m
It is a left join, unless you want soem EXISTS/UNION construct. Not tested:
SELECT
COALESCE(N.VALUE, M.ABC)
FROM
MYTABLE M
LEFT JOIN
NAMEVALUEMAP N ON M.VALUE N.ABC
If you really want to avoid JOINs...
SELECT
ABC
FROM
MYTABLE M
WHERE
NOT EXISTS (SELECT * FROM NAMEVALUEMAP N WHERE M.VALUE N.ABC)
UNION ALL
SELECT
VALUE
FROM
NAMEVALUEMAP N
WHERE
EXISTS (SELECT * FROM MYTABLE M WHERE M.VALUE N.ABC)
Edit:
The SELECT *, 1 or NULL in EXISTS question again
Try EXISTS (SELECT 1/0...)
Mentioned in ANSI SQL 1992 Standard too, page 191
EDIT:
SELECT
COALESCE(
(SELECT NAME_ FROM NAMEVALUEMAP WHERE VALUE_ =
(SELECT ABC FROM MYINNERTABLE inner_ WHERE inner_.ID = outer_.ID)
),
<int to string>(
SELECT ABC FROM MYINNERTABLE inner_ WHERE inner_.ID = outer_.ID
)
)
FROM
MYTABLE outer_
where column function <int to string> is appropriate for sqlserver. In mysql it would be CAST(). Without conversion, the query will throw a wobbly about the mismatched datatypes.

Resources