In sql server 2005, i in the query builder, i select "Add group by" to automatically
add the group by clause to all of the fields i selected. If one or more of those fields are a bit type, i get an error. Why is this? Is casting the column to TINYINT a good fix?
It looks like a limitation of that tool. if you just write the actual sql yourself in SQL Server Management Studio, it will work.
here is my test code:
CREATE TABLE Test2
(ID INT,
bitvalue bit,
flag char(1))
GO
insert into test2 values (1,1,'a')
insert into test2 values (2,1,'a')
insert into test2 values (3,1,'a')
insert into test2 values (4,1,'b')
insert into test2 values (5,1,'b')
insert into test2 values (6,1,'b')
insert into test2 values (7,1,'b')
insert into test2 values (10,0,'a')
insert into test2 values (20,0,'a')
insert into test2 values (30,0,'a')
insert into test2 values (40,0,'b')
insert into test2 values (50,0,'b')
insert into test2 values (60,0,'b')
insert into test2 values (70,0,'b')
select * from test2
select count(*),bitvalue,flag from test2 group by bitvalue,flag
OUTPUT
ID bitvalue flag
----------- -------- ----
1 1 a
2 1 a
3 1 a
4 1 b
5 1 b
6 1 b
7 1 b
10 0 a
20 0 a
30 0 a
40 0 b
50 0 b
60 0 b
70 0 b
(14 row(s) affected)
bitvalue flag
----------- -------- ----
3 0 a
3 1 a
4 0 b
4 1 b
(4 row(s) affected)
The tools don't allow some operations such as indexing or grouping on bit columns. Raw SQL does.
Note, you can't aggregate on bit columns. You have to cast first. Of course, averaging a bit columns is kinda pointless, but MAX/MIN is useful as a OR/AND spanning multiple rows.
Related
I have a WHILE LOOP in an SQL query.
I have a table with 5 ROWS matching the counter
I'm randomizing 2048 rows and want to INSERT 1 - 5 over those rows, randomly into a single column but what I'm getting is, the query loops once over 2048 and inserts "1", then it loops a second time and inserts "5", then inserts, "3", then "4", and finally "2".
What I seek is loop through one time through the 2048 rows and insert randomly, 1 - 5 through 2048 rows (1 time) in the single column.
Here's the SQL which works but wrong.
declare #counter int
SET #counter = 1
BEGIN TRAN
WHILE (#counter <= 6)
BEGIN
SELECT id, city, wage_level
FROM myFirstTable
ORDER BY NEWID()
UPDATE myFirstTable
SET wage_level = #counter
SET #counter = #counter + 1
CONTINUE
END
COMMIT TRAN
The values in the table that contain 5 rows are irrelevant but fact that the "IDs" in that table are from 1 - 5 "ARE."
I'm close, but no cigar...
The result should be something like this:
id-----city------wage_level
---------------------
1 Denver 2
2 Chicago 3
3 Seattle 5
4 Los Angeles 1
5 Boise 4
---
2047 Charleston 2
2048 Rochester 1
And so on...
Thanks, everyone
No need for a loop. SQL works best on a set based approach.
Here is one way to do it:
Create and populate sample table (Please save us this step in your future questions)
CREATE TABLE myFirstTable
(
id int identity(1,1),
city varchar(20),
wage_level int
)
INSERT INTO myFirstTable (city) VALUES
('Denver'),
('Chicago'),
('Seattle'),
('Los Angeles'),
('Boise')
The update statement:
UPDATE myFirstTable
SET wage_level = (ABS(CHECKSUM(NEWID())) % 5) + 1
Check the update:
SELECT *
FROM myFirstTable
Results:
id city wage_level
1 Denver 3
2 Chicago 3
3 Seattle 2
4 Los Angeles 4
5 Boise 3
Explanation: use NEWID() to generate a guid, CHECKSUM() to get a number based on that guid, ABS() to get only positive values, % 5 to get only values between 0 and 4, and finally, + 1 to get only values between 1 and 5:
I am trying to puzzle out a trigger in a SQL Server database. I am a student working on a summer project so I am no pro at this but can easily learn it.
This is a simplified version of my database table sorted by rank:
ID as primary key
ID | RANK
--------------
2 | NULL
1 | 1
3 | 2
4 | 3
7 | 4
The objective for me right now is to have the ability to insert/delete/update the rank and maintain incremental order of ranks in the database without any missing numbers in available positions along with no duplicates.
/* Insert new row */
INSERT INTO TABLE (ID, RANK) VALUES (6, 4)
/* AFTER INSERT */
ID | RANK
--------------
2 | NULL
1 | 1
3 | 2
4 | 3
6 | 4 <- new
7 | 5 <- notice how the rank increased to make room for the new row
I think doing this in a trigger is the most efficient/easiest way; although I may be wrong.
Alternatively to a trigger, I have made a temporary solution that uses front end code to run updates on each row when any rank is changed.
If you know how or if a trigger could do this please share.
EDIT: Added scenarios
The rank being inserted would always take its assigned number. Everything that is greater than or equal to the one being inserted would increase.
The rank causing the trigger will always have priority to claim its number while everything else will have rank increased to accommodate.
If rank is the highest number then the trigger would ensure that the number is +1 of the max.
This may work for you. Let me know.
DROP TABLE dbo.test
CREATE TABLE dbo.test (id int, ranke int)
INSERT INTO test VALUES (2, NULL)
INSERT INTO test VALUES (1, 1)
INSERT INTO test VALUES (3, 2)
INSERT INTO test VALUES (4, 3)
INSERT INTO test VALUES (7, 4)
GO
CREATE TRIGGER t_test
ON test
AFTER INSERT
AS
UPDATE test set ranke += 1 WHERE ranke >= (select max(ranke) from inserted) and id <> (select max(id) from inserted)
GO
INSERT INTO test values (6,4)
INSERT INTO test values (12,NULL)
SELECT * FROM test
I need help with a transitive query in SQL Server.
I have a table with [ID] and [GRPID].
I would like to update a third column [NEWGRPID] based on the following logic:
For each [ID], get its GRPID;
Get all of the IDs associated with the GRPID from (1);
Set [NEWGRPID] equal to an integer (variable that is incremented by 1), for all of the rows from step (2)
The idea is several of these IDs are "transitively" linked across different [GRPID]s, and should all be having the same [GRPID].
The below table is the expected result, with [NEWGRPID] populated.
ID GRPID NEWGRPID
----- ----- ------
1 345 1
1 777 1
2 777 1
3 345 1
3 777 1
4 345 1
4 999 1
5 345 1
5 877 1
6 999 1
7 877 1
8 555 2
9 555 2
Try this code:
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
BEGIN
DROP TABLE #tmp;
END;
SELECT GRPID, count (*) AS GRPCNT
INTO #tmp
FROM yourtable
GROUP BY GRPID
UPDATE TGT
SET TGT.NEWGRPID = SRC.GRPCNT
FROM yourtable TGT
JOIN #tmp ON #tmp.GRPID = TGT.GRPID
If the values are likely to change over time you should think about a computed column or a trigger.
I have a scenario where in I want a field in a table to be incremented sequentially.
Suppose I have a table Test, with columns TestID, TestResult1,2 etc.. and TestCount.
I have data bulk inserted into the table. Some of the records may be retests, which means new data to be inserted matches existing records in the table, Test Count should be updated.Matching is done on TestID
If the table is as follows:
TestID TestResult1 TestResult2.. TestCount
12 1 1 1
12 2 2 2
13 4 1 1
Data to be inserted in
TestID TestResult1 TestResult2..
12 3 5
12 2 2
The table should be updated as
TestID TestResult1 TestResult2.. TestCount
12 1 1 1
12 2 2 2
13 4 1 1
12 3 5 3
12 2 2 4
I tried adding a trigger on the table to update the TestCount Counting the number of records that matches. But it was updating the table as follows
TestID TestResult1 TestResult2.. TestCount
12 1 1 1
12 2 2 2
13 4 1 1
12 3 5 3
12 2 2 3
CREATE TRIGGER trgTestCount
on Test
AFTER INSERT
AS
Update g
Set TestCount= (Select Count(*)+1 from Test g join INSERTED g1 where g.TestID=g1.TestID )
from Test g
This is a SSIS package and I use a dataflow task to load data from STg table to test table.
Can you tell me what I am doing wrong here?
If you can change the table structure, I would suggest adding an Identity column, change the TestCount column to a computed column, and have it's value as the count of distinct test ids that are the same is the current row test id and the create date is lower than the current value of the Identity column.
This will eliminate the need for triggers and will handle inserting multiple records with the same test id automatically.
How to auto increment update a column in a SQL Server table based on sorting other columns and restart the increment after value changes in other columns.
My table structure and data is like that:
Name Class OldSrNo NewSrNo
----------------------------
aa 1 1 1
bb 1 2 2
aa 1 3 3
bb 2 4 1
cc 2 5 2
dd 2 6 3
aa 2 7 4
I want to update old sr no to look like NewSrNo
Are you asking this,
Declare #t table (Name varchar(50), Class int, OldSrNo int)
insert into #t values
('aa', 1, 1)
,('bb', 1, 2)
,('aa', 1, 3)
,('bb', 2, 4)
,('cc', 2, 5)
,('dd', 2, 6)
,('aa', 2, 7)
select *,
row_number()over(partition by class order by class)NewSrNo
from #t