How to arrange data in sql server table - sql-server

I tried many query to achieve the expected result , I couldn't find any solution.
Actual:-
ID | EmpDailyFee | EmpMonthlyFee | CompDailyFee | CompMnthlyFee
1 NULL 12 NULL NULL
1 50 NULL NULL NULL
1 60 NULL NULL NULL
2 50 NULL NULL NULL
3 NULL 30 NULL NULL
Expected :-
ID | EmpDailyFee | EmpMonthlyFee | CompDailyFee | CompMnthlyFee
1 50 12 NULL NULL
1 60 12 NULL NULL
2 50 NULL NULL NULL
3 NULL 30 NULL NULL

This looks like a table smell to me since the rows are sharing the same ID value but with different EmpDailyFee/EmpMonthlyFee values. But in this particular case you can get your expected output like this:
SELECT t1.ID, t1.EmpDailyFee, t2.EmpMonthlyFee
FROM #Test t1
INNER JOIN #Test t2 ON t1.ID = t2.ID
WHERE t1.EmpDailyFee IS NOT NULL AND t2.EmpMonthlyFee IS NOT NULL
UNION ALL
SELECT t1.ID, t1.EmpDailyFee, t1.EmpMonthlyFee
FROM #Test t1
WHERE (t1.EmpDailyFee IS NOT NULL OR t1.EmpMonthlyFee IS NOT NULL) AND t1.ID NOT IN
(
SELECT t3.ID
FROM #Test t3
INNER JOIN #Test t2 ON t3.ID = t2.ID
WHERE t3.EmpDailyFee IS NOT NULL AND t2.EmpMonthlyFee IS NOT NULL
)
This has been tested on SQL Fiddle
Note: The reason why I did not include CompDailyFee and CompMnthlyFee is because the values of both the actual and expected results were NULL. I am trying to write a "simple-as-possible" query based on what OP has provided.

If you're trying to insert or update data this could be the solution, customizing it on your needings
IF EXISTS (SELECT 1 FROM Employee WHERE ID = 1)
UPDATE Employee SET EmpMonthlyFee= #Value WHERE ID = 1
ELSE
INSERT Employee(ID,EmpDailyFee,EmpMonthlyFee,CompDailyFee,CompMnthlyFee)
VALUES(1,NULL,#value,NULL,NULL)

declare #t table (ID int,Empfee int,monthlyfee int,compdailyfee int,Cmpnymonthlyfee int)
insert into #t (ID,Empfee,monthlyfee,compdailyfee,Cmpnymonthlyfee)
values (1,NULL,12,NULL,NULL),
(1,50,NULL,NULL,NULL),
(1,60,NULL,NULL,NULL)
;with cte as (
select t.ID,t.Empfee,
tt.monthlyfee,
t.compdailyfee,
t.Cmpnymonthlyfee,
ROW_NUMBER()OVER(PARTITION BY t.ID,tt.monthlyfee ORDER BY t.ID,tt.monthlyfee)RN
from #t t
CROSS APPLY #t tt
where t.Empfee IS NULL OR tt.monthlyfee IS NOT NULL)
select C.ID,
C.Empfee,
C.monthlyfee,
C.compdailyfee,
C.Cmpnymonthlyfee from cte c
where c.Empfee IS NOT NULL AND c.monthlyfee IS NOT NULL

Can be done using COALESCE as well.
SELECT T1.ID,
T2.EmpDailyFee,
COALESCE(T1.EmpMonthlyFee , T2.EmpMonthlyFee) EmpMonthlyFee,
COALESCE(T1.CompDailyFee , T2.CompDailyFee) CompDailyFee ,
COALESCE(T1.CompMnthlyFee , T2.CompMnthlyFee) CompMnthlyFee
FROM
(SELECT * FROM Tab WHERE EmpDailyFee IS NULL)T1
JOIN
(SELECT * FROM Tab WHERE EmpDailyFee IS NOT NULL)T2
ON T1.ID = T2.ID
I have gone one step ahead and assumed that values from the first row will take priority if not null(As for the 3rd column in OP). This part can be neglected if not required.

Related

SPLIT A STRING THEN CHANGE IT TO DECIMAL AND MULTIPLY IT TO A VALUE IN ANOTHER TABLE

I need to separate from Table 1, Col1 that contains 'currency' and 'value' or ';'.
Table1
Col1
GBP;185.00
EUR;152.46
;
SEK;364.55
USD;364.55
Then in Table 2 I use 'CurrCode' to join with 'Value' from Table1.
Table2
CurrValue CurrCode
11.01 GBP
NULL EUR
---
9.44 SEK
9.01 USD
I build this code but the amount of data is too big, It works only until 9000 columns and then crashes. Is there a way to work this around?
SELECT
Col1
,(reverse(substring(reverse(Col1),0,charindex(';',reverse(Col1))))) as LocalValue
,c.currVALUE
,substring(Col1,1,charindex(';',Col1)-1) as Currency
,case when Col1 like 'EUR;%' then (reverse(substring(reverse(Col1),0,charindex(';',reverse(Col1)))))
else try_convert(numeric(18,5),(reverse(substring(reverse(Col1),0,
charindex(';',reverse(Col1))))))* c.CurrValue
end as ValueEUR
from b
left join c
on c.CurrencyCode = substring(Col1,1,charindex(';',Col1)-1)
The desired result is a table that shows CurrValue, Currecy and ValueEUR (where 'CurrValue' * 'Localvalue' = 'ValueEUR'):
LocalValue Currency ValueEUR
185.33 GBP 2040.48
152.46 EUR 152.46
0 --- 0
364.55 SEK 3441.35
364.55 USD 3284.60
NOTE: When Currency is EUR, CurrValue is NULL and ValueEUR is the same as LocalValue.
I have created a CTE vTable1 for demo only. I think it's better for you to create a view.
IF OBJECT_ID('tempdb..#Table1') IS NOT NULL DROP TABLE #Table1
IF OBJECT_ID('tempdb..#Table2') IS NOT NULL DROP TABLE #Table2
create table #Table1
(
Col1 varchar(100)
)
create table #Table2
(
CurrValue decimal(18,2),
CurrCode varchar(3)
)
INSERT INTO #Table1
values
('GBP;185.00'),
('EUR;152.46'),
(';'),
('DKK;364.55'),
('SEK;364.55'),
('USD;364.55')
INSERT INTO #Table2
VALUES
(11.01, 'GBP'),
(null, 'EUR'),
(null, '---'),
(9.44, 'SEK'),
(9.01, 'USD')
;WITH vTable1 (Currency, Value)
as
(
SELECT SUBSTRING(Col1,0,CHARINDEX(';',Col1)) AS Currency
,TRY_CONVERT(DECIMAL(18,2), SUBSTRING(Col1,CHARINDEX(';',Col1)+1, LEN(Col1))) as Value
FROM #Table1
)
SELECT COALESCE(t1.Value, 0) as CurrValue
,t2.CurrCode as Currency
,CONVERT(DECIMAL(18,2), COALESCE(t2.CurrValue * t1.Value, t1.Value, 0)) AS ValueEUR
FROM vTable1 as t1
RIGHT JOIN #Table2 as t2
on t1.Currency = t2.CurrCode
Here is the code that solved it:
SELECT
t.Col1
,COALESCE(TRY_CONVERT(DECIMAL(18,3),SUBSTRING(t.Col1,CHARINDEX(';',t.Col1)+1,
LEN(t.Col1))),0) AS LocalValue
,COALESCE(c.CurrValue,0) as CurrValue
,SUBSTRING (t.Col1, 0, CHARINDEX(';',t.Col1)) AS Currency
,COALESCE((c.CurrValue*TRY_CONVERT(DECIMAL(18,3),SUBSTRING(t.Col1,CHARINDEX(';',t.Col1)+1,LEN(t.Col1)))),COALESCE(TRY_CONVERT(DECIMAL(18,3),SUBSTRING(t.Col1,CHARINDEX(';',t.
Col1)+1, LEN(t.Col1))),0)) AS ValueEUR
from Table1 as t
left join Table1 as c
on c.CurrCode = SUBSTRING (Col1, 0, CHARINDEX(';',Col1))

Inserting 2 insert query records in SQL server

need your expert
when inserting query like this :
use tabelmantap
delete from T_CekUser
insert into T_CekUser(T_21SI)
select tbla.MASA
from
(
select * from T_21SI
union
select * from T_21SI
) as tbla
where tbla.THN_DATA = '2014' and tbla.KEY_NPWP = '01.576.555.5-123.000'
insert into T_CekUser(T_23SI)
select tblb.MASA from
(
select * from T_23SI
union
select * from T_23SI
) as tblb
where tblb.THN_DATA = '2014' and tblb.KEY_NPWP = '01.576.555.5-123.000'
all that query is in one line/page query in sql server
and i get results like this :
T_21SI | T_23SI
1 null
2 null
3 null
4 null
null 2
null 3
been tired, looking around for answer or solution as i wanna be like this :
T_21SI | T_23SI
1 2
2 3
3 null
4 null
null null
null null
all file type are int
i have made insert using select from two tables (using inner join) but result is not being expected
any help would be really appreciated..thanks
Try using the PIVOT statement details are here. https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

Sql 2000 data format using a group by query

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.

if value is null get previous value sql server 2008

I have table that looks like this
Id Description
5 Null
4 This is a description
3 This is a description
2 Null
1 Null
I need to create an update statement that will update the null value if the previous value is not null.
Id Description
5 This is a description
4 This is a description
3 This is a description
2 Null
1 Null
Any advice or assistance would be much appreciated.
I think this is what you're looking for:
update toupdate
set description = updateto.description
from yourtable toupdate
join yourtable updateto on updateto.id = toupdate.id - 1
where updateto.description is not null
and toupdate.description is null;
SQL Fiddle Demo
This produces the following results:
ID DESCRIPTION
5 This is a description
4 This is a description
3 This is a description
2 (null)
1 (null)
EDIT: As pointed out by comment by Aaron Bertrand.
If your IDs aren't consecutive, you can use the row_number() function to join on instead of the ids:
with cte as (
select *, row_number() over (order by (select null)) rn
from yourtable
)
update toupdate
set description = updateto.description
from cte toupdate
join cte updateto on toupdate.rn = updateto.rn - 1
where updateto.description is not null
and toupdate.description is null;
You can change your order by criteria as needed.
Updated SQL Fiddle
The most common way (that I am aware of) to do this sort of thing is with a self-join:
-- WARNING: Untested Code
UPDATE YourTable
SET Origin.Description = Proxy.Description
FROM YourTable Origin
JOIN YourTable Proxy
ON Origin.Id = Proxy.Id - 1
WHERE Origin.Description IS NULL
AND Proxy.Description IS NOT NULL
This will join YourTable to itself so that one row looks like this:
Origin.Id | Origin.Description | Proxy.Id | Proxy.Description
------------------------------------------------------------------
5 | NULL | 4 | This is a description
EDIT
If you are not guaranteed always incrementing IDs then you will want to use ROW_NUMBER:
;WITH NumberedRows
AS
(
SELECT *
, ROW_NUMBER() OVER(ORDER BY Id) AS [Row #]
FROM YourTable
)
SELECT *
FROM NumberedRows Origin
JOIN NumberedRows Proxy
ON Origin.Id = Proxy.Id - 1
WHERE Origin.Description IS NULL
AND Proxy.Description IS NOT NULL

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