B
B
Boris the Animal2016-07-17 21:44:15
SQL
Boris the Animal, 2016-07-17 21:44:15

Is it efficient to query to get the first few records from the database using JOIN?

In order to make it convenient for you to test various options (if the request is not very well made and you want to help), I will post the code for creating tables and filling them with test data.
If there is a better request, show the code, I would like to see it, and not just verbally hear advice on what to change.

IF OBJECT_ID('Users') IS NOT NULL 
  DROP TABLE Users;

IF OBJECT_ID('Groups') IS NOT NULL 
  DROP TABLE Groups;

CREATE TABLE Groups(
  GroupID INT NOT NULL,
  Name NVARCHAR(40) NOT NULL,
  Replicated TINYINT NOT NULL DEFAULT(0),
  CONSTRAINT PK_Groups_GroupID PRIMARY KEY(GroupID)
  );
GO

CREATE TABLE Users(
  UserID INT NOT NULL IDENTITY(1, 1),
  Name NVARCHAR(40) NOT NULL,
  GroupID INT NOT NULL,
  CONSTRAINT PK_Users_UserID PRIMARY KEY(UserID),
  CONSTRAINT FK_Users_GroupID FOREIGN KEY(GroupID) REFERENCES Groups(GroupID)
  );
GO

INSERT INTO Groups (GroupID, Name)
  VALUES 
    (1, N'Группа 1'),
    (2, N'Группа 2'),
    (3, N'Группа 3'),
    (4, N'Группа 4'),
    (5, N'Группа 5'),
    (6, N'Группа 6'),
    (7, N'Группа 7'),
    (8, N'Группа 8'),
    (9, N'Группа 9'),
    (10, N'Группа 10'),
    (11, N'Группа 11'),
    (12, N'Группа 12'),
    (13, N'Группа 13'),
    (14, N'Группа 14'),
    (15, N'Группа 15'),
    (16, N'Группа 16'),
    (17, N'Группа 17');
GO

INSERT INTO Users (Name, GroupID)
  VALUES 
    (N'1 Владимир Сенцов', 1),
    (N'1 Дмитрий Логинов', 1),
    (N'2 Адрей Астапов', 2),
    (N'2 Владимир Астапов', 2),
    (N'3 Александр Астапов', 3),
    (N'3 Адрей Серков', 3),
    (N'4 Адрей Астапов', 4),
    (N'4 Борис Хорошилов', 4),
    (N'5 Адрей Серков', 5),
    (N'5 Адрей Животное', 5),
    (N'6 Антон Миллер', 6),
    (N'6 Владимир Животное', 6),
    (N'7 Дмитрий Логинов', 7),
    (N'7 Адрей Астапов', 7),
    (N'8 Адрей Серков', 8),
    (N'8 Александр Астапов', 8),
    (N'9 Адрей Серков', 9),
    (N'9 Адрей Синдеев', 9),
    (N'10 Борис Хорошилов', 10),
    (N'10 Адрей Серков', 10),
    (N'11 Анатолий Сенцов', 11),
    (N'11 Антон Миллер', 11),
    (N'12 Борис Серков', 12),
    (N'12 Анатолий Астапов', 12),
    (N'13 Борис Хорошилов', 13),
    (N'13 Адрей Серков', 13),
    (N'14 Адрей Животное', 14),
    (N'14 Борис Миллер', 14),
    (N'15 Адрей Серков', 15),
    (N'15 Александр Астапов', 15),
    (N'16 Александр Серков', 16),
    (N'16 Адрей Синдеев', 16),
    (N'17 Борис Хорошилов', 17),
    (N'17 Адрей Миллер', 17);
GO

As a result, we have several groups, each of which has 2 people.
Some explanation, not relevant to the essence of the question :
Replicated = 2 means that the data was sent, but it was not confirmed that they were stored on the receiving side. If the data is updated on the sending side, then 1 will be set in Replicated and when I receive a response from the receiving side, I simply transfer to Replicated = 1 only the data that was Replicated = 2. That is, if the data that I just sent was updated before confirmation, then at least the data was saved on the receiving side, but I will read it again (already updated) and send it again. This is not particularly relevant to the question, but so that you understand what's what.
Now the query itself for fetching non-replicated data :
DECLARE @GroupIDs TABLE(ID INT)
INSERT INTO @GroupIDs(ID) SELECT TOP(3) GroupID FROM Groups WHERE Replicated <> 1;

SELECT 
  g.GroupID,
  g.Name AS GroupName,
  g.Replicated,
  u.UserID,
  u.Name AS UserName
FROM
Groups g
INNER JOIN @GroupIDs ids ON g.GroupID = ids.ID
LEFT OUTER JOIN Users u ON u.GroupID = ids.ID;

UPDATE Groups SET Replicated = 2 WHERE GroupID IN(SELECT ID FROM @GroupIDs);

Question :
I need to get the first few records from the Groups table and everyone in that group. Is the request made effectively? How and can it be optimized at all?
This is how I confirm that the data has been saved on the receiving side, after receiving a confirmation of successful data saving from the receiving side:
UPDATE Groups SET Replicated = 1 WHERE ID = @ID AND Replicated > 1;

Auxiliary code :
After executing the query above, we mark the previously received data as replicated and the next time the query is called above, this data will no longer be selected from the database. Just for the convenience of testing queries in the current example.
UPDATE Groups SET Replicated = 1 WHERE Replicated = 2;

We return everything to its original state.
UPDATE Groups SET Replicated = 0 WHERE Replicated = 1; 

SELECT COUNT(GroupID) AS Replicated_1 FROM Groups WHERE Replicated = 1;
SELECT COUNT(GroupID) AS Replicated_2 FROM Groups WHERE Replicated = 2;

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
res2001, 2016-07-17
@res2001

1. In my opinion, a temporary table is not needed. Rewrite update without temporary table.
2. To select the first 3 records, I would add some kind of sorting. Although this is not required.
3.Instead of the primary key, I would make a unique clustered index.
In general, queries are not complicated, there is nothing to optimize.

A
Artyom Karetnikov, 2016-07-18
@art_karetnikov

Good. In my opinion - a perversion. Here is the creation of a temporary table from groups, then join it with the same groups...
SELECT TOP(3) GroupID FROM Groups g
LEFT JOIN Users u ON u.GroupID = g.ID
WHERE Replicated <> 1;
All. Here are your three entries, any unsynced. Insert the fields you need from both tables yourself. And second, discover the mysteries of the select ... output ... command.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question