Query to subtract all numbers in a column - sql

I don't think code should be necessary here but let me know if you'd like it anyways.
I had to delete an entire set of entries in one of my tables. These entries were being organized by a integer value that increased with intervals. Is there a way that I can write a query so that all the values in a particular column will update with a -1 value?
So for example, lets say I had this table
| Red | 1 |
| Orange | 2 |
| Yellow | 3 |
| Green | 4 |
| Cyan | 6 |
| Blue | 7 |
| Purple | 8 |
| Violet | 9 |
could I write a single query so that cyan - violet's numbers all subtracted by one rather than doing a unique update for every entry?
| Red | 1 |
| Orange | 2 |
| Yellow | 3 |
| Green | 4 |
| Cyan | 5 |
| Blue | 6 |
| Purple | 7 |
| Violet | 8 |

Use Cte to update and Row_number() to generate sequential numbers
; WITH cte
AS (SELECT ( Row_number()OVER( ORDER BY id) )rn,*
FROM yourtable)
UPDATE cte
SET id = rn

Related

Is there a way to alternate the order of a result based off one id while keeping groupings based off another id in SQL?

I have this query in Postgresql:
(SELECT q.question, q.category_id, a.id, a.question_id, a.answer
FROM questions q, answers a
WHERE q.id = a.question_id
AND category_id = 1
AND question_id
BETWEEN (SELECT property FROM users WHERE email = 'test#test.com')
AND (SELECT property FROM users WHERE email = 'test#test.com') + 14)
UNION
(SELECT q.question, q.category_id, a.id, a.question_id, a.answer
FROM questions q, answers a
WHERE q.id = a.question_id
AND category_id = 2
AND question_id
BETWEEN (SELECT laws FROM users WHERE email = 'test#test.com')
AND (SELECT laws FROM users WHERE email = 'test#test.com') + 16)
ORDER BY question_id, id
that currently returns results in this format:
+-----------------------------+-------------+-------------+--------+
| question | category_id | question_id | answer |
+-----------------------------+-------------+-------------+--------+
| What color is the sky? | 1 | 16 | blue |
| What color is the sky? | 1 | 16 | green |
| What color is the sky? | 1 | 16 | purple |
| What color is the sky? | 1 | 16 | red |
| What color is a firetruck? | 1 | 17 | orange |
| What color is a firetruck? | 1 | 17 | teal |
| What color is a firetruck? | 1 | 17 | red |
| What color is a firetruck? | 1 | 17 | green |
| What color is dirt? | 2 | 18 | green |
| What color is dirt? | 2 | 18 | green |
| What color is dirt? | 2 | 18 | green |
| What color is dirt? | 2 | 18 | green |
+-----------------------------+-------------+-------------+--------+
What I want to do is alternate the order based off the category_id, so the category id would be alternating like this: 1,2,1,2, but I want to keep the groups based off the question_id. So the result would look like this:
+-----------------------------+-------------+-------------+--------+
| question | category_id | question_id | answer |
+-----------------------------+-------------+-------------+--------+
| What color is the sky? | 1 | 16 | blue |
| What color is the sky? | 1 | 16 | green |
| What color is the sky? | 1 | 16 | purple |
| What color is the sky? | 1 | 16 | red |
| What color is dirt? | 2 | 18 | green |
| What color is dirt? | 2 | 18 | green |
| What color is dirt? | 2 | 18 | green |
| What color is dirt? | 2 | 18 | green |
| What color is a firetruck? | 1 | 17 | orange |
| What color is a firetruck? | 1 | 17 | teal |
| What color is a firetruck? | 1 | 17 | red |
| What color is a firetruck? | 1 | 17 | green |
+-----------------------------+-------------+-------------+--------+
I've tried to using ORDER BY row_number() OVER (PARTITION BY t.category_id ORDER BY t.category_id)
but that just results in each being alternated without being grouped by question_id
I think you want the following order by clause:
order by
rank() over(partition by category_id order by question_id),
question_id,
id
Basically this interleaves the categories/questions tuples.
Notes:
use standard, explicit joins (from ... join ... on) rather than old-school, implicit joins (from ..., ... where ...); this is prehistoric syntax, that should not be used in new code
it is rather likely that your query could be simplified to not use union; if you were to ask another question with sample data, and desired results, one might be able to suggest

Count Duplicate Values SQL Server 2014

Say I have the below dataset
ID| Last | FavColor
-------------------------
1 | Johnson | BLUE
1 | Johnson | RED
2 | Thomas | YELLOW
3 | Anderson| BLUE
3 | Anderson| RED
3 | Anderson| BLUE
4 | Phillips| ORANGE
4 | Phillips| ORANGE
How do I create a query that still keeps the ID, Last and FavColor, but shows a occurrence count of each color?
ID| Last | FavColor | Color Count |
-----------------------------------------
1 | Johnson | BLUE | 1 |
1 | Johnson | RED | 1 |
2 | Thomas | YELLOW | 1 |
3 | Anderson| BLUE | 2 |
3 | Anderson| RED | 1 |
3 | Anderson| BLUE | 2 |
4 | Phillips| ORANGE | 2 |
4 | Phillips| ORANGE | 2 |
I attempted to do a COUNT(FavColor) PARTITION BY(ID), but am not sure how to count duplicates.
You want to partition by id as well as favcolor:
SELECT ID,
Last ,
FavColor,
COUNT(*) over (partition BY id, favcolor) color_count
FROM your_table t;

Set multiple column values from previous row using Postgres SQL

Assume you have a series of responses from people on what their favorite colors are. This information is stored in a SQL table:
| id | favorite_color | friend_recommendation_id |
|----|----------------|--------------------------|
| 1 | green | |
| 2 | blue | |
| 3 | yellow | |
| 4 | green | |
| 5 | yellow | |
| 6 | green | |
My goal is to write a Postgres SQL query that would fill the friend_recommendation column with the id of the most recent person to respond with the same color as the provided individual. This would result in the following table:
| id | favorite_color | friend_recommendation_id |
|----|----------------|--------------------------|
| 1 | green | |
| 2 | blue | |
| 3 | yellow | |
| 4 | green | 1 |
| 5 | yellow | 3 |
| 6 | green | 4 |
Note that id 6 is filled with 4 and not 1
I've tried using variables and subselects, but am struggling with how to apply the select for each result from the parent query.
Use a subquery to calculate the field
SQL Fiddle Demo
SELECT "id", "favorite_color", (SELECT MAX("id")
FROM colors c2
WHERE c2."favorite_color" = c1."favorite_color"
AND c2."id" < c1."id"
) as friend_recommendation_id
FROM colors c1
OUTPUT
| id | favorite_color | friend_recommendation_id |
|----|----------------|--------------------------|
| 1 | green | (null) |
| 2 | blue | (null) |
| 3 | yellow | (null) |
| 4 | green | 1 |
| 5 | yellow | 3 |
| 6 | green | 4 |
Can also be write like this:
SELECT c1."id", c1."favorite_color", MAX(c2."id") as friend_recommendation_id
FROM colors c1
LEFT JOIN colors c2
ON c2."favorite_color" = c1."favorite_color"
AND c2."id" < c1."id"
GROUP BY c1."id", c1."favorite_color"
ORDER BY c1."id";
UPDATE
UPDATE colors target
SET "friend_recomendation_id" = ( SELECT MAX("id")
FROM colors c2
WHERE c2."favorite_color" = target."favorite_color"
AND c2."id" < target."id")

query all records with maximum id in different group from a table in rails environment

I have a table orders with id and color columns, id is unique column.
| id | color |
| ---- | ----- |
| 1 | Red |
| 2 | Red |
| 3 | Green |
| 4 | Green |
| 5 | Blue |
| 6 | Blue |
I hope to get all rows with maximum id in their color group, the query result should be
| 2 | Red |
| 4 | Green |
| 6 | Blue |
How can I query the correct result in rails environment with Sqlite3 (dev env) and PostgreSQL 9.3 (production env)
Thanks.
you could write:
Order.group(:color).maximum(:id)
Order.select('color, MAX(id) as maxid').group(:color)
Optionally, you can add .order(:color) before the .group clause. Should work with either database.

Select 1 random record per category using sql

I have a single large table conveniently called mytable, with three columns: id, cat_group, cat_other. I would like to select a random element from each cat_group using SQL. How can I do it?
Example data
| id | cat_group | cat_other |
+----+-----------+-----------+
| 1 | red | fred |
| 2 | blue | sarah |
| 3 | blue | peter |
| 4 | green | spot |
| 5 | red | peter |
Acceptable result
| cat_group | id | cat_other |
+-----------+----+-----------+
| red | 5 | peter |
| blue | 2 | sarah |
| green | 4 | spot |
Also good
| cat_group | id | cat_other |
+-----------+----+-----------+
| red | 1 | fred |
| blue | 3 | peter |
| green | 4 | spot |
I have seen some similar questions on SO, but I get lost in the implementation specifics. I'm using postgresql, but the answer should be able to be generalised across different databases.
Sqlfiddle at http://sqlfiddle.com/#!1/b42c8/2
Here is one way, using row_number():
select cat_group, id, cat_other
from (select mytable.*,
row_number() over (partition by cat_group order by random()) as seqnum
from mytable
) as t
where seqnum = 1
The same idea works in other databases. However, the random number function may differ. For instance, in as SQL Server, rand() returns only one value per query -- as opposed to per row. There you would use newid().