I'm trying to implement a restricted auto-number within multiple tables which can be used as common ground to facilitate work allocation.
Currently I have a range of queries that select a number of pieces of work sorted by descending value. I'd like to implement a fixed auto-number within these tables that repeats in the following format:
1,2,3,4,5,6,7,8,9,10,11,1,2,3,4,5,6,7,8,9,10,11...etc.
This is to allow me to link each piece of work in the table to an owner assigned a number from 1 - 11.
I'm more than happy to receive alternate suggestions!
Thanks in advance.
J.
You can run a query:
Select
YourTable.Id,
(Select Count(*)
From YourTable As T
Where T.ID < YourTable.Id) Mod 11 + 1 AS
ID11
From
YourTable;
where Id is the primary key.
Related
UPDATE: Not sure if what I'm trying to achieve is possible but thanks for all the help - is it appropriate to request this be deleted? I don't want the contributors to lose the upvotes I've given them for their help.
UPDATE: Just to be clear, when I say columns are created 'dynamically' I mean without developer input so they are an unknown. They are still properly defined columns in a standard database table - I just don't know the names of all of them. :-D
I have a table with columns created dynamically (very rarely but I'm trying to make this as robust as possible). I need to output the SUM of these columns, ordered by highest first but obviously also need the column names in the first row (as otherwise the data is useless). I've retrieved the columns using the information_schema.columns method in to PHP and thought I'd iterate through the columns performing a SUM but if I do that, they are not ordered numerically.
This can be built in to an SP (I'm assuming it will have to be done in an SP due to complexity). I believe I probably need to involve 'PIVOT' somewhere but that is the limit of my knowledge!
So to SUMmarise (see what I did there :-D )
I have a table definition with columns like this:
volunteerID INT
yearAdded DATETIME
willySize111to120 INT
willySize121to130 INT
willySize131to140 INT
willySize141to150 INT
I'd like to return a dataset like this in a query where I can specify the year:
sizeBracket count
willySize111to120 98
willySize121to130 76
willySize131to140 54
willySize141to150 23
Every time I think I've figured out a way to do it, I hit another wall.
Thanks for any help or pointers!
Bob
Assuming that your original table has a 1 in the correct bracket for each volunteer and a 0 in all other brackets:
SELECT bracket.sizeBracket, COUNT(*) count
FROM (
SELECT CASE
WHEN willySize111to120 THEN 'willySize111to120'
WHEN willySize121to130 THEN 'willySize121to130'
WHEN willySize131to140 THEN 'willySize131to140'
WHEN willySize141to150 THEN 'willySize141to150'
END CASE sizeBracket
FROM ... -- < Table Name
WHERE ... -- < Date Selection Logic
) bracket
GROUP BY sizeBracket
ORDER BY count DESC
UPDATE
Based on a raw data table willySize with columns
volunteerID INT
yearAdded DATETIME
willySize INT
You could run the following query
SELECT
CONCAT(
'willySize',
ROUND(willySize-6,-1)+1,
'to',
ROUND(willySize+4,-1)
) sizeBracket,
COUNT(*) count
FROM willySize
GROUP BY sizeBracket
ORDER BY count DESC
Lets say I have a simple table with 'appID' and 'userID', which his populated for each app that used by a specific user (ever). (These IDs refer to other tables which have information about app and user which do not matter for this question).
For example:
appID userID
1 1
1 2
2 2
Here, we can see app #1 was used by two users, but app #2 was used by one user.
I want to generate statistics for the most commonly used app using a MySQL query, if possible. The query would return a list of sorted results with the appID and the total number of unique users using it.
I did some research but cannot figure out an easy to do this in SQL. If anyone can help, I'd appreciate it. If it requires a very long and involved stored procedure, I may just switch to doing some of the calculations in code (at least initially) since it will be easier to troubleshoot.
SELECT appID, COUNT(*) FROM myTable GROUP BY appID ORDER BY COUNT(*) DESC
I have the following table my_table with primary key id set to AUTO_INCREMENT.
id group_id data_column
1 1 'data_1a'
2 2 'data_2a'
3 2 'data_2b'
I am stuck trying to build a query that will take an array of data, say ['data_3a', 'data_3b'], and appropriately increment the group_id to yield:
id group_id data_column
1 1 'data_1a'
2 2 'data_2a'
3 2 'data_2b'
4 3 'data_3a'
5 3 'data_3b'
I think it would be easy to do using a WITH clause, but this is not supported in MySQL. I am very new to SQL, so maybe I am organizing my data the wrong way? (A group is supposed to represent a group of files that were uploaded together via a form. Each row is a single file and the the data column stores its path).
The "Psuedo SQL" code I had in mind was:
INSERT INTO my_table (group_id, data_column)
VALUES ($NEXT_GROUP_ID, 'data_3a'), ($NEXT_GROUP_ID, 'data_3b')
LETTING $NEXT_GROUP_ID = (SELECT MAX(group_id) + 1 FROM my_table)
where the made up 'LETTING' clause would only evaluate once at the beginning of the query.
You can start a transaction do a select max(group_id)+1, and then do the inserts. Or even by locking the table so others can't change (insert) to it would be possible
I would rather have a seperate table for the groups if a group represents files which belong together, especially when you maybe want to save meta data about this group (like the uploading user, the date etc.). Otherwise (in this case) you would get redundant data (which is bad – most of the time).
Alternatively, MySQL does have something like variables. Check out http://dev.mysql.com/doc/refman/5.1/en/set-statement.html
I have a table like so
ID NAME
----------- -----------
1 JON
2 JIM
3 BOB
(3 row(s) affected)
What I need its code to select a number that does not exit in the column ID and out put it to a file so in this instance it will be "4".
What i need it to do is start at 1 then check 2,3,and so on until if finds a a number that does not exists in the table.
This code will have to be in SQL Server 2008
What you need is a numbers table or list:
Declare #MaxValue int;
Set #MaxValue = 100;
With Numbers As
(
Select 1 As Value
Union All
Select Value + 1
From Numbers
Where Value <= #MaxValue
)
Select Min(N.Value)
From Numbers As N
Left Join MyTable As T
On T.Id = N.Value
Where T.Id Is Null
OPTION (MAXRECURSION 0)
Can you specify why you need this? It sounds like there may be a better way to satisfy the overall need.
However, if all you need is the next number in the sequence, then this should work:
SELECT MAX(ID) + 1 FROM Table
Edit: I just noticed from Thomas' answer (and re-inspecting the question) that it looks like you're looking for the first gap, which may or may not be the next number. But I guess the overall point still remains... why?
Edit: I'm glad you accepted an answer, but I still think there's more to this. For example, if you just want to be able to "reserve" an ID then there are a couple ways to accomplish this.
GUIDs are good for application-generated IDs, but shouldn't be used as primary keys for performance reasons. You can have a second column as a GUID and use that within your application, allowing a simple auto-increment column to be the primary key. There are further performance considerations to be made, and you should research it.
Conversely, there's something called the Hi/Lo Algorithm for reserving ranges of database IDs. It uses integers, which are great for indexing and make great primary keys. It leaves gaps in the sequence, but that's to be expected anyway even with a regular auto-generated column (such as when a record is deleted).
If there is a requirement that there shouldn't be gaps in the identifiers, that sounds like an odd business requirement and should be analyzed for its true needs. Something like that shouldn't spill over into the primary key in your data persistence.
I am trying to find a way to get a random selection from a large dataset.
We expect the set to grow to ~500K records, so it is important to find a way that keeps performing well while the set grows.
I tried a technique from: http://forums.mysql.com/read.php?24,163940,262235#msg-262235 But it's not exactly random and it doesn't play well with a LIMIT clause, you don't always get the number of records that you want.
So I thought, since the PK is auto_increment, I just generate a list of random id's and use an IN clause to select the rows I want. The problem with that approach is that sometimes I need a random set of data with records having a spefic status, a status that is found in at most 5% of the total set. To make that work I would first need to find out what ID's I can use that have that specific status, so that's not going to work either.
I am using mysql 5.1.46, MyISAM storage engine.
It might be important to know that the query to select the random rows is going to be run very often and the table it is selecting from is appended to frequently.
Any help would be greatly appreciated!
You could solve this with some denormalization:
Build a secondary table that contains the same pkeys and statuses as your data table
Add and populate a status group column which will be a kind of sub-pkey that you auto number yourself (1-based autoincrement relative to a single status)
Pkey Status StatusPkey
1 A 1
2 A 2
3 B 1
4 B 2
5 C 1
... C ...
n C m (where m = # of C statuses)
When you don't need to filter you can generate rand #s on the pkey as you mentioned above. When you do need to filter then generate rands against the StatusPkeys of the particular status you're interested in.
There are several ways to build this table. You could have a procedure that you run on an interval or you could do it live. The latter would be a performance hit though since the calculating the StatusPkey could get expensive.
Check out this article by Jan Kneschke... It does a great job at explaining the pros and cons of different approaches to this problem...
You can do this efficiently, but you have to do it in two queries.
First get a random offset scaled by the number of rows that match your 5% conditions:
SELECT ROUND(RAND() * (SELECT COUNT(*) FROM MyTable WHERE ...conditions...))
This returns an integer. Next, use the integer as an offset in a LIMIT expression:
SELECT * FROM MyTable WHERE ...conditions... LIMIT 1 OFFSET ?
Not every problem must be solved in a single SQL query.