I have a number of user ID's. I am inserting these into a group table which will contain a column for the user's ID and the group ID. This will allow me to use the query "SELECT user_id FROM groups WHERE group_id = '3';" to retrieve user ID's of all the members of group 3.
My problem is that I currently have a list of all users IDs, which I got from a form, using the statements :
int i = 0;
String[] names = { Request.Form["usernames"]Split(' ') }; //retrieving names from form
List<int> user_ids = new List<int>();
foreach(string name in names){
int user_id = db.QueryValue("SELECT user_id FROM users WHERE username = name");
user_ids.Add(user_id); //now I have a list of all user_ids
}
I now wish to insert this data into the groups table, where all of the user_id values in the list will have the same group_ID. How can I do this?
//create a group from users
"INSERT INTO group (group_id, user_id) VALUES(?,?);
What you are talking about is a many-many relationship. You already have a users table:
**users**
userid
username
You need an additional table in the middle. The group table will just have something like:
**group***
groupid
groupName
You would then have a table in the middle. This table would look something like this:
**user_groups**
userid
groupid
You could still use your code to insert a user,
int i = 0;
String[] names = { Request.Form["usernames"]Split(' ') }; //retrieving names from form
List<int> user_ids = new List<int>();
foreach(string name in names){
int user_id = db.QueryValue("SELECT user_id FROM users WHERE username = name");
user_ids.Add(user_id); //now I have a list of all user_ids
}
After this, you would insert a group:
insert into group(groupName) values("Sample Group")
Then you could retrieve the group id and use that to insert into user_groups
select groupid from group where groupname="Sample Group"
insert into user_groups(userid,groupid) values(...
Also, the table structure should include primary keys and foreign keys (much like #sixlettervariables' answer)
In order to make this cleaner, you'll probably want to refactor your database setup slightly such that a third table relates users to groups:
users (user_id pk, ...)
groups (group_id pk, ...)
membership (user_id fk, group_id fk) unique(user_id, group_id)
When you needed to make a new group you simply insert into the groups table, obtain the group_id, and use that to populate the membership table for each of the users in that group.
You can use the select as the input to the insert
INSERT INTO group (group_id, user_id)
SELECT 1, user_id FROM users WHERE username in ("name1", name2")
You can join the names array back together with some commas.
You will need to iterate the user_ids list and do a separate insert statement for each user id.
You can insert all of the User ID's from one table into another using a sub-select and union statement as follows:
INSERT INTO group_table_name([user_id]) SELECT [user_id] FROM table_name
UNION ALL
By the way, you might want to change that table name since "group" is a keyword in SQL Server. Just a tip.
Insert Into GroupTable (GroupId, UserID) Select GroupID, USerID from UserTable group by GroupID, UserID)
This would work :)
Assuming you already know 3, you can do this without pulling the user ids into a local list and then inserting them individually (put in quotes specifically because the OP has their query in a similar string):
"INSERT dbo.group(group_id, user_id)
SELECT 3, user_id
FROM dbo.users
WHERE username = name;"
If you don't already know the group id, then please explain how you determined the group id should be 3.
EDIT based on further info.
CREATE TABLE dbo.Groups
(
GroupID INT IDENTITY(1,1) PRIMARY KEY,
GroupName NVARCHAR(255) NOT NULL UNIQUE
);
CREATE TABLE dbo.GroupUsers
(
GroupID INT NOT NULL FOREIGN KEY
REFERENCES dbo.Groups(GroupID),
UserID INT NOT NULL FOREIGN KEY
REFERENCES dbo.Users(UserID),
PRIMARY KEY(GroupID, UserID)
);
Now when you want to create a new group and add users to it:
DECLARE #GroupID INT;
INSERT dbo.Groups(GroupName) SELECT N'whatever (unique)';
SELECT #GroupID = SCOPE_IDENTITY();
Now you can loop through each user id:
INSERT dbo.GroupUsers(GroupID, UserID) SELECT #GroupID, <userid>;
Related
I have the following SQL Table:
Name Description Id UserId CreatedDate
UserSet1 Desc1 1 Abc 06/01/2018
UserSet1 Desc2 2 Def 06/02/2018
UserSet2 Desc for 2 5 NewUser 06/04/2018
UserSet2 Desc for 2 7 NewUser 06/19/2018
What I want to extract from the above table is just the latest Id for each Name so that I could get the following output
Name Description Id UserId CreatedDate
UserSet1 Desc2 2 Def 06/01/2018
UserSet2 Desc for 2 7 NewUser 06/19/2018
Since Id 2 & 7 are the latest entries in the table for UserSet1 & UserSet2, I would like to display that instead of all the entries in the table.
Any inputs how can I get the desired result.
I am open for solutions directly returning the output or any linq (C#) solutions as well. Ie returning the entire dataset and then using linq to filter the above.
EDIT: Since you are looking for the highest number ID, the GROUP BY method would probably be easier to work with.
Using a window function:
SELECT *
FROM (
SELECT Name, Description, Id, UserId, CreatedDate
, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY CreatedDate DESC) AS rn
FROM myTable
) s1
WHERE rn = 1
I don't have an instance of dynamoDB to test on, but I believe it can use the ROW_NUMBER() window function.
Thanks everyone for pointing to right direction. I have got this working with the below code of Linq and C#:
var results = response.GroupBy(row => row.Name)
.SelectMany(g => g.OrderByDescending(row => row.Id).Take(1));
For the initial tests this seems to be working. Let me know if you think this has come issues.
This should be a general SQL answer:
SELECT * FROM yourtable Y1
WHERE Id = (SELECT MAX(Id)
FROM yourtable Y2
WHERE Y2.Name = Y1.Name)
If it was MS SQL you could use Partition By command, otherwise most performant way would be:
select * from Table
where Id in (
select Max(Id) from Table
Group By Name
)
not sure if you can leave Name out of the Select statement, you might need to do:
select * from Table
where Id in (
Select Id from
(select Name, Max(Id) as Id from Table
Group By Name)
)
I have two tables, I would like to get one value based on some max date.
Here are the tables structures:
Items (ItemId, Name)
ItemData(ItemDataId, ItemFK, Invoice, EntryDate) - ItemFK is the foreign key of ItemId in Items table
What I know is the Name of the item only. I would like to get the latest Invoice based on the EntryDate (and the name).
I 1st need to get the itemid based on the name, then get the invoice based on the itemid but only the last one (so using max(enteydate).
How to do so with using innerjoin (or some other join sql query)?
You join to a derived table, which is a subquery with an alias.
select yourfields
from someTable join otherTablesMaybe on something
join (
select id, max(datefield) maxDate
from someTable
where whatever
group by id ) derivedTable on someTable.id = derivedTable.id
and someTable.datefield = maxDate
where whatever
The two where whatevers should be the same.
I would like to join data from tables from two databases. One is filed with predefined values (itemId, itemName) and other is filled by user (itemId, itemName, userId). Atributes itemId and itemName are the same, from first table we select all data, from second we select data by userId and combine these two results.
Joined data should be distinguish because ids are autoincrement and could be the same(doubled). We would like to fill drop down list with this data for example with datasource and dictionary (int is itemId, string is itemName) we could only have valueFiled and valueText in dropDownList but ids of these two tables could be the same and lather we don`t know from wich table is item selected by id.
Is there any elegant way to joint this, maybe with temp tables that we always when user is logged in join these two tables in temp table etc...
Thank you for your answers
I think you're looking for a union. Use a literal value to identify the source.
select 'predefined' as source, itemid, itemname
from predefined_values_table
union all
select 'user', itemid, itemname
from user_supplied_values_table
where userid = ?;
If you can accommodate only two columns, you might be able to use something like this instead. But you'll have to undo the string concatenation to get the id number.
select 'p:' || itemid, itemname
from predefined_values_table
union all
select 'u:' || itemid, itemname
from user_supplied_values_table
where userid = ?;
I have three tables
Employee (ID numeric, Name varchar)
Login (ID numeric, UserName varchar, Password varchar)
EmployeeLogin (ID numeric, EmployeeID, LoginID)
Relation is one employee can have multiple login. How will I get all the Login Name of a particular Employee.
I am able to fetch single record using the code given below but how will I get multiple records
using (var context = new AllEntities())
{
var query = from c in context.Employees
where c.ID == 9
select c;
}
The EmployeeLogin table seems redundant if you only have a one-to-many relationship between Employee and Login. You could just place a column EmployeeId in the Login table. The setup you have right now supports many-to-many between Employee and Login.
If you change your model according to my suggestion you could then get all Logins for a EmployeeId like this:
var query = from c in context.Logins
where c.EmployeeID == 9
select c;
If you keep your current model you could get all logins for an employee id like this:
var query = from l in context.Logins
join el in context.EmployeeLogins
on l.LoginId equals el.LoginId
where el.EmployeeID == 9
select l;
You should have all of the Logins in a navigation property on the Employee entity. See this tutorial:
http://www.asp.net/web-forms/tutorials/getting-started-with-ef/the-entity-framework-and-aspnet-getting-started-part-1
You can let the Entity Framework get the related data automatically or you can do it manually; for descriptions of lazy vs. eager loading see these tutorials:
http://www.asp.net/web-forms/tutorials/getting-started-with-ef/the-entity-framework-and-aspnet-getting-started-part-2
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application
Here is the my problem: I have a SQL Server database called emp. It has an employee table (with userid int column). I need to retrieve the last record of the userid in employee table with increment userid value + 1. At the moment I did it on the my GUI. So how do I write a sql query for it?
To return the the record with the highest userid, you can do:
SELECT TOP 1 userid
FROM employee
ORDER BY userid DESC
or...
SELECT MAX(userid)
FROM employee
If your plan is to then increment the userid manually and insert a new record with that new ID, I'd recommend against doing that - what if 2 processes try to do it at the same time? Instead, use an IDENTITY column as userid and let the incrementing be handled for you automatically
You shouldn't be manually incrementing the userid column, use an IDENTITY column instead. That will automatically add 1 for you for every new row.
CREATE TABLE Employees (
UserId INT IDENTITY PRIMARY KEY NOT NULL,
UserName NVARCHAR(255) NOT NULL,
// etc add other columns here
)
If you really really have to select the highest userid it is a very simple query:
SELECT MAX(UserId) + 1
FROM Employees
[Edit]
Based on your comments, you should use the SELECT MAX(UserId) + 1 FROM Employees query. But be aware that this does not guarantee the number will be the ID. Normally you would not show an Id value until after the record has been saved to the database.
This will give you last inserted record, If you don't have Identity column.
EXECUTE ('DECLARE GETLAST CURSOR DYNAMIC FOR SELECT * FROM [User]')
OPEN GETLAST
FETCH LAST FROM GETLAST
CLOSE GETLAST
DEALLOCATE GETLAST
If you have set identity than you can use following.
SELECT top(1) ID from [YourTable] order by ID desc
To have the new userid before saving, create a NextId table.
Before inserting the user, get the new value from NextId:
UserId = SELECT Coalesce(NextId, 0) + 1 from NextId
Then update the NextID table:
UPDATE NEXTID SET NextId = IserID
And then use that value in your user creation code
You can get gaps, there are more complicated methods to avoid them; but I think this will do