I have an table (always ordered by ID ascending) with 5 records as such :
ID Sequence
1 1
2 2
3 3
4 4
8 3
9 3
And the desired output is :
ID Sequence
1 1
2 2
3 3
4 6
8 4
9 5
Looks like 3 direct updates to me, no point over complicating it:
UPDATE table SET sequence = 6 WHERE id = 4
UPDATE table SET sequence = 4 WHERE id = 8
UPDATE table SET sequence = 5 WHERE id = 9
If you want to do this in one step:
update t
set sequence = v.sequence
from t join
(values (4, 6), (8, 4), (9, 5)
) v(id, sequence)
on t.id = v.id;
If you have to do many of these updates, then separate calls to update incur extra overhead.
Related
I am trying to process data within the same table.
Input:
Table
id sort value
1 1 1
2 1 8
3 2 0
4 1 2
What I want to achieve is obtain for each id, the first encountered value for all value equal to its sort, and this ordered by id.
Output
Table
id sort value new
1 1 1 1
2 1 8 1
3 2 0 0
4 1 2 1
I tried to self join the table, but I constantly get relation not found. I tried with a case statement but I don't see how can I connect to the same table, I get the same error, relation not found.
The beauty of SQL is that many requirements (yours included) can be verbosely described in very similar way they are finally coded:
with t(id, sort, value ) as (values
(1, 1, 1),
(2, 1, 8),
(3, 2, 0),
(4, 1, 2)
)
select t.*
, first_value(value) over (partition by sort order by id) as "new"
from t
order by id
id
sort
value
new
1
1
1
1
2
1
8
1
3
2
0
0
4
1
2
1
fiddle
I have a table
order_id user_id lunch_type box
1 1 A 5
2 1 B 1
3 1 C 3
4 2 C 4
5 2 B 2
6 3 A 7
7 4 C 6
8 4 A 1
9 5 C 9
10 5 B 2
From the tabel above, I want to make a new tabel like this
user_id Lunch_A Lunch_B, Lunch_C total
1 5 1 3 9
2 4 2 0 6
3 7 0 0 7
I don't know how to query like that
Let's say your exisinting table is Orders and new table is OrdersSummary, so you can create new table by :
CREATE TABLE OrdersSummary
AS ( SELECT
user_id,
count(*) as total,
count(IF(lunch_type = "A", 1, NULL)) as Lunch_A,
count(IF(lunch_type = "B", 1, NULL)) as Lunch_B,
count(IF(lunch_type = "C", 1, NULL)) as Lunch_C
from Orders group by user_id
);
Explanation:
Creating table from another table using CREATE TABLE as (Select columns from )
While selecting records from existing table we're grouping rows on the basis of user_id so count(*) will give use total count and we want to count of lunch_type (A, B, C) separately so in count expression we're using IF clause so it row has specific lunch_type only then it'll be counted
I would like a simple query to solve this.
We have a simple table with 4 columns for merging client data. We have to create a loop to transverse the data until the ToClient cannot be found in the FromClient Row. We have one person that has been merged 5 times.
FromClient# ToClient# Userid Timestamp
1 2
2 3
3 4
4 5
5 6
7 8
What I want is a table created that looks like the following, so it is a simple join for reporting.
FromClient# ToClient#
1 6
2 6
3 6
4 6
5 6
7 8
Any pointers would be great.
Thanks.
Try this using Recursive Common Table Expression (RCTE):
with
mytab (FromClient#, ToClient#) as
(
values
(1, 2)
, (2, 3)
, (3, 4)
, (4, 5)
, (5, 6)
, (7, 8)
)
, t (FromClient#, ToClient#) as
(
select FromClient#, ToClient#
from mytab a
where not exists (select 1 from mytab b where b.FromClient# = a.ToClient#)
union all
select a.FromClient#, t.ToClient#
from t, mytab a
where a.ToClient# = t.FromClient#
)
select *
from t
order by FromClient#;
I have a table with part of data like below . I have done order by on edition_id .
Now there is further requirement of ordering laungauge_id which depends on value of edition_id.
Edition_id refers to city from which a newspaper is published.
Language_id refers to different languages in which newspaper is
published.
So suppose edition_id = 5 it means New Delhi.
For New Delhi language_id are 13(English ), 5 (Hindi) ,1(Telugu ),4(Urdu).
What i want is to display for New Delhi , is display all English articles first , followed by hindi , followed by Telugu followed by Urdu.
If edition_id=1 then order of language_id should be 13,1,2.
Similarly ,
If edition_id=5 then order of language_id should be 13,5,1,4
Right now what I have is
Edition_id | Language_id
1 1
1 2
1 13
1 1
1 13
1 2
5 4
5 1
5 1
5 4
5 13
5 5
5 13
What is required
Edition_id | Language_id
1 13
1 13
1 1
1 1
1 2
1 2
5 13
5 13
5 5
5 1
5 1
5 4
5 4
How to do this ? Please help.
Is something like this possibe
Select * from <table>
order by edition_id ,
case when edition=6 then <order specified for language_id ie 13,5,1,4>
I would create a supplementary ranking table. I would then JOIN to provide your sort order. Eg:
EDITION_SORT_ORDER
EDITION_ID LANGUAGE_ID RANK
---------- ----------- ----
1 13 1
1 1 2
1 2 3
5 13 1
5 5 2
5 1 3
5 4 4
Using this table in a query might look like this:
SELECT E.EDITION_ID, E.LANGUAGE_ID
FROM <TABLE> E LEFT OUTER JOIN EDITION_SORT_ORDER S ON
E.EDITION_ID = S.EDITION_ID AND
E.LANGUAGE_ID = S.LANGUAGE_ID
ORDER BY S.RANK
This way you can add other rules in future, and it isn't a huge mess of CASE logic.
Alternatively, if you want to avoid a JOIN, you could create a stored function which did a similar lookup and returned a rank (based on passed parameters of EDITION_ID and LANGUAGE_ID).
If you must use CASE, then I'd confine it to a function so you can re-use the logic elsewhere.
If there is no mathematical logic behind it, I would insert another column that can be used for proper sorting.
If you cannot do this, you can simply type out the rules for the relation like this:
Order By Edition_Id,
case Edition_id
when 1 then
case Language_id
when 13 then 1
when 1 then 2
when 2 then 3
end
when 5 then
case Language_id
when 13 then 1
when 5 then 2
when 1 then 3
when 4 then 4
end
end
without a fixed order colum you could things like that, but the logic is not comprehensible.
Assuming first criteria is length of Language_id,
Second is Edition_id= Language_id,
rest is order of Language_id it could or work this way:
Declare #t table(Edition_id int, Language_id int)
insert into #t values
(1, 1),
(1, 2),
(1, 13),
(1, 1),
(1, 13),
(1, 2),
(5, 4),
(5, 1),
(5, 1),
(5, 4),
(5, 13),
(5, 5),
(5, 13);
Select * from #t
order by Edition_id,Case when len (Cast(Language_ID as Varchar(10)))=1 then '1' else '0' end
+case when Edition_id=Language_id then '0' else '1' end
,Language_ID
You've probably considered this but if your desired ordering is always based of the actual alphabetical name of the language then there would usually be a table with the language description that you could join with and then sort by. I base this on your quote below.
...English articles first , followed by hindi , followed by Telugu
followed by Urdu.
SELECT E.EDITION_ID, E.LANGUAGE_ID, LN.LANGUAGE_NAME
FROM <TABLE> E LEFT OUTER JOIN <LANGUAGE_NAMES> LN ON
E.LANGUAGE_ID = LN.LANGUAGE_ID
ORDER BY 1, 3
Can i use several WHEN conditions in UPDATE clause to update a single column.
I want to update table TABLE having columns ID and NAME:
Is below query correct?
UPDATE TABLE
SET id = CASE id
WHEN id IN (2, 3, 4) THEN 1
WHEN id= 5 THEN 8
WHEN id IN(9, 7) THEN 6
WHERE name = 'abc'
Yes, that is allowed, but remove ID after CASE. And, you need to END your case.
UPDATE TABLE
SET ID = CASE
when ID in (2,3,4)
then 1
when ID = 5
then 8
when ID in (9,7)
then 6
END
where NAME = 'abc'
There are two alternate syntaxes for CASE. As above, and the other is where you want to compare a single value against others, like this:
UPDATE TABLE
SET ID = CASE ID
when 2
then 1
when 5
then 8
when 7
then 6
END
where NAME = 'abc'
Case comes in two versions:
version 1:
Case Id
When 2 Then 1
When 3 Then 1
When 4 Then 1
When 5 Then 8
When 7 Then 6
When 9 Then 6
End
version 2:
Case
When Id in (2,3,4) Then 1
When Id = 5 Then 8
When Id in (9,7) Then 6
End
Both of above are equivilent