Copy rows and change 1 value? [duplicate] - sql

This question already has answers here:
MySQL: How to copy rows, but change a few fields?
(8 answers)
Closed 5 years ago.
How would I copy entire rows within a table and change one value?
insert into user (
user_id,account_id,user_type_cd,name,e_mail_addr,
login_failure_cnt,admin_user,primary_user
)
select * from pnet_user where account_id='1'
But now I want to change 1 to 2 on the inserted entries.
But now I want to change 1 to 3 on the inserted entries.
But now I want to change 1 to .... on the inserted entries.
But now I want to change 1 to 1000 on the inserted entries.
It will copy and write down 1000 times (only changing id ).

I'm not completely sure I understand what you're asking. If you want to copy the records where Account_ID = 1 into new rows and change Account_ID to 2 (or whatever number), this should work for you:
insert into user (user_id,account_id,user_type_cd,name,e_mail_addr,
login_failure_cnt,admin_user,primary_user)
select user_id,2,user_type_cd,name,e_mail_addr,
login_failure_cnt,admin_user,primary_user
from pnet_user where account_id='1'
Basically, replace Account_ID with the value 2. If Account_ID is a varchar, use single quotes around it instead.

Related

Select values that are not included on a table [duplicate]

This question already has answers here:
How to select all records from one table that do not exist in another table?
(15 answers)
Closed 1 year ago.
I have one table "Cells" with Primary key "Cell_ID". There are 160 ID's/records. There is one other table, for example "Customers" where I use a field "CellID", which is a table list using row source the field "Cell_ID" from the table "Cells".
I would like to create a query that will return me all the Cell_ID values that are not used on the Customers.CellId field.
My first thought was to use something like the following:
SELECT Cells.Cell_ID
FROM Cells
WHERE Cells.Cell_ID NOT IN (
SELECT Customers.CellID
FROM Customers);
Your method is conceptually okay. But there is a problem if Customers.CellId is ever NULL. If that is the case, then the query will return no rows.
For this reason, I recommend never using NOT IN with a subquery. Instead, use NOT EXISTS:
SELECT c.Cell_ID
FROM Cells as c
WHERE NOT EXISTS (SELECT 1
FROM Customers as cu
WHERE c.Cell_ID = cu.CellID
);

PostgreSQL copy row minus a few columns

How can I duplicate a row, excluding a couple columns, without listing out every column I want to copy? My concern is doing it as an include vs. an exclude is that if I add a new column or remove a column from the table, I have to remember to update this stored procedure that does the clone to list the new columns.
You have to explicitly list columns or use *. No shortcut for * except short_list. You can try hacking this with dynamic sql, preparing query from existing columns from eg information_schema.columns:
t=# select column_name,ordinal_position from information_schema.columns where table_name ='s160' order by ordinal_position;
column_name | ordinal_position
-------------+------------------
id | 1
a | 2
b | 3
c | 4
d | 5
(5 rows)
So saving previous column list ang comparing it against current would give you new columns and you can adapt changes in execute format(..., but honestly - it leads to more problems then specifying explicit list of columns every time.

SQLite UPSERT with 2 constraints [duplicate]

This question already has answers here:
SQLite INSERT - ON DUPLICATE KEY UPDATE (UPSERT)
(5 answers)
SQL: How to update or insert if doesn't exist?
(2 answers)
Closed 9 years ago.
I have an sql table with 3 columns, none of which is UNIQUE ( but the pair name + role is ):
Name | Role | Votes
What I need to do is, write an sqllite query that stick to the following rules :
If a row with the given name and role already exist, votes is
incremented by 1
If not, a new row is created with Votes = 1
I've looked into INSERT OR REPLACE and this great post but it doesn't seem to help me that much, and I'm not even sure INSERT OR REPLACE is a viable option, since something like
INSERT OR REPLACE INTO words (name,role,votes)
VALUES ('foo','bar', coalesce((
select votes from words where name = 'foo' and role='bar'),0)+1)
always insterts and never replace
You simply need to create unique index over your 2 columns for this to work:
CREATE UNIQUE INDEX words_name_role_idx ON words (name,role)
Note that you do not create unique index for any single column, but for combination of 2 as a whole.
After that, your REPLACE INTO statement should start working correctly:
REPLACE INTO words (name,role,votes) VALUES ('foo','bar',
coalesce((
SELECT votes FROM words
WHERE name = 'foo' AND role='bar'),0
)+1
)
(note that I have changed counter to votes above).
This query will update your record with +1.
update todo set text='raj',complete='raj',pk=((SELECT pk FROM todo where text='raj' and complete='raj')+1) where (SELECT pk FROM todo where text='raj' and complete='raj')
EDIT YOUE QUERY
update words set name='foo',role='bar', votes =((SELECT votes FROM words where name='foo' and role='bar')+1) where (SELECT votes FROM words where name='foo' and role='bar')
And make insert query if this condition will not true.

Only the latest data show on table

How to create table or maybe trigger that doing like this below?
Date Data
2/6/2013 2
2/6/2013 1
2/6/2013 3
2/6/2013 1
2/6/2013 0
The table at top will alternately as input for next table below, but only the last input will show at table below. The input will alternately from 2 until 0
Just say the input start from 2 - 1 - 3 - 1 - 0, and only 0 will show on table. How to make the trigger? 0 only data, not something unique. Only the latest input will show on table. Remember the table below triggered table at top to take the data.
I just want every time new input inserted, the data that already existed delete and only the new input will show
Data
0
I think you just want a VIEW that shows the latest value.
The following would be the query you'd use for your view...
SELECT TOP 1 Data FROM Table ORDER BY Date DESC
EDIT To do exactly what you want you'd just need a stored procedure for inserting.
-- Copy old value into history
INSERT INTO History SELECT * From Table WHERE yourCondition = True
-- Delete old value
DELETE FROM Table WHERE yourCondition = True
-- Insert new value
INSERT INTO Table VALUES(#Date, #Data)
Now Table will contain only 1 row with the latest value, while History will contain all the old values. This is completely non-standard and irrational, but should be exactly what you want. If you don't need history you can just remove the first INSERT statement.

SQL query select from table and group on other column

I'm phrasing the question title poorly as I'm not sure what to call what I'm trying to do but it really should be simple.
I've a link / join table with two ID columns. I want to run a check before saving new rows to the table.
The user can save attributes through a webpage but I need to check that the same combination doesn't exist before saving it. With one record it's easy as obviously you just check if that attributeId is already in the table, if it is don't allow them to save it again.
However, if the user chooses a combination of that attribute and another one then they should be allowed to save it.
Here's an image of what I mean:
So if a user now tried to save an attribute with ID of 1 it will stop them, but I need it to also stop them if they tried ID's of 1, 10 so long as both 1 and 10 had the same productAttributeId.
I'm confusing this in my explanation but I'm hoping the image will clarify what I need to do.
This should be simple so I presume I'm missing something.
If I understand the question properly, you want to prevent the combination of AttributeId and ProductAttributeId from being reused. If that's the case, simply make them a combined primary key, which is by nature UNIQUE.
If that's not feasible, create a stored procedure that runs a query against the join for instances of the AttributeId. If the query returns 0 instances, insert the row.
Here's some light code to present the idea (may need to be modified to work with your database):
SELECT COUNT(1) FROM MyJoinTable WHERE AttributeId = #RequestedID
IF ##ROWCOUNT = 0
BEGIN
INSERT INTO MyJoinTable ...
END
You can control your inserts via a stored procedure. My understanding is that
users can select a combination of Attributes, such as
just 1
1 and 10 together
1,4,5,10 (4 attributes)
These need to enter the table as a single "batch" against a (new?) productAttributeId
So if (1,10) was chosen, this needs to be blocked because 1-2 and 10-2 already exist.
What I suggest
The stored procedure should take the attributes as a single list, e.g. '1,2,3' (comma separated, no spaces, just integers)
You can then use a string splitting UDF or an inline XML trick (as shown below) to break it into rows of a derived table.
Test table
create table attrib (attributeid int, productattributeid int)
insert attrib select 1,1
insert attrib select 1,2
insert attrib select 10,2
Here I use a variable, but you can incorporate as a SP input param
declare #t nvarchar(max) set #t = '1,2,10'
select top(1)
t.productattributeid,
count(t.productattributeid) count_attrib,
count(*) over () count_input
from (select convert(xml,'<a>' + replace(#t,',','</a><a>') + '</a>') x) x
cross apply x.x.nodes('a') n(c)
cross apply (select n.c.value('.','int')) a(attributeid)
left join attrib t on t.attributeid = a.attributeid
group by t.productattributeid
order by countrows desc
Output
productattributeid count_attrib count_input
2 2 3
The 1st column gives you the productattributeid that has the most matches
The 2nd column gives you how many attributes were matched using the same productattributeid
The 3rd column is how many attributes exist in the input
If you compare the last 2 columns and the counts
match - you can use the productattributeid to attach to the product which has all these attributes
don't match - then you need to do an insert to create a new combination