SQL random name generator not inserting first and last name in the same row

你离开我真会死。 提交于 2019-12-24 04:37:26

问题


I managed to create a simple query that selects a random first and last name and inserts them into a result table. I wanted to create something I could interchange with the various tests I run where I have to manufacture a lot of data. Here is the code (I only included 5 first and last names each for simplicity purposes):

SELECT 
    FirstName, LastName
FROM
    (SELECT TOP 1 
         FirstName 
     FROM 
         (SELECT 'John' AS FirstName 
          UNION SELECT 'Tim' AS FirstName 
          UNION SELECT 'Laura' AS FirstName
          UNION SELECT 'Jeff' AS FirstName
          UNION SELECT 'Sara' AS FirstName) AS First_Names 
     ORDER BY NEWID()) n1
FULL OUTER JOIN 
    (SELECT TOP 1
         LastName 
     FROM (SELECT 'Johnson' AS LastName 
           UNION SELECT 'Hudson' AS LastName 
           UNION SELECT 'Jackson' AS LastName
           UNION SELECT 'Ranallo' AS LastName
           UNION SELECT 'Curry' AS LastName) AS Last_Names 
     ORDER BY NEWID()) n2 ON [n1].FirstName = [n2].LastName
WHERE 
    n1.FirstName IS NOT NULL OR n2.LastName IS NOT NULL

Here are the results:

FirstName LastName 
NULL      Hudson
John      NULL

I want the results to return one row with a first and last name randomly generated so that each row would have a complete name (no NULL values). I'm sure it's something simple I am overlooking.


回答1:


The following code will allow you to generate a series of random names, where a cross join solution allows only one at a time. Not sure if you need to do this more than once, but if you do:

create table #table (firstname varchar(50), lastname varchar(50))

declare @counter int = 1 
declare @max int = 5 --set number of repetitions here
declare @a varchar(50)
declare @b varchar(50)

while @counter <= @max
begin

SET @a = (SELECT TOP 1 FirstName 
    FROM (SELECT 'John' AS FirstName 
    UNION SELECT 'Tim' AS FirstName 
    UNION SELECT 'Laura' AS FirstName
    UNION SELECT 'Jeff' AS FirstName
    UNION SELECT 'Sara' AS FirstName) AS First_Names ORDER BY NEWID())

SET @b =
    (SELECT TOP 1 LastName 
    FROM (SELECT 'Johnson' AS LastName 
    UNION SELECT 'Hudson' AS LastName 
    UNION SELECT 'Jackson' AS LastName
    UNION SELECT 'Ranallo' AS LastName
    UNION SELECT 'Curry' AS LastName) AS Last_Names ORDER BY NEWID())

    insert into #table values (@a, @b)

    set @counter = @counter + 1
end

select * from #table



回答2:


The problem is your join. This is how you can do it:

SELECT FirstName, LastName
FROM
(SELECT TOP 1 FirstName 
FROM (SELECT 'John' AS FirstName 
UNION SELECT 'Tim' AS FirstName 
UNION SELECT 'Laura' AS FirstName
UNION SELECT 'Jeff' AS FirstName
UNION SELECT 'Sara' AS FirstName) AS First_Names ORDER BY NEWID())n1
CROSS JOIN 
(SELECT TOP 1 LastName 
FROM (SELECT 'Johnson' AS LastName 
UNION SELECT 'Hudson' AS LastName 
UNION SELECT 'Jackson' AS LastName
UNION SELECT 'Ranallo' AS LastName
UNION SELECT 'Curry' AS LastName) AS Last_Names ORDER BY NEWID())n2



回答3:


If you need to get more than 1 combination here is an alternative to using a loop for this type of thing.

declare @max int = 5;

with FirstNames(FName) as
(
    SELECT 'John' UNION ALL
    SELECT 'Tim' UNION ALL
    SELECT 'Laura' UNION ALL
    SELECT 'Jeff' UNION ALL
    SELECT 'Sara'
)
, LastNames(LName) as
(
    SELECT 'Johnson' UNION ALL
    SELECT 'Hudson' UNION ALL
    SELECT 'Jackson' UNION ALL
    SELECT 'Ranallo' UNION ALL
    SELECT 'Curry'
)
, SortedNames(FName, LName, RowNum) as
(
    select FName
        , LName
        , ROW_NUMBER() over (Order by newid())
    from FirstNames
    cross join LastNames
)

select FName
    , LName
from SortedNames
where RowNum <= @max
order by NEWID();



回答4:


If you are wanting to efficiently generate multiple rows (you did mention needing to generate a lot of sample data), then here is something I just posted earlier today on another question on S.O. ( Msg 6522, Level 16 warning during execution of clr stored procedure ). That question dealt with randomizing 4 fields instead of just two, but I am keeping those extra fields here so you can see how easy it is to adapt to other scenarios you might have. It is rather simple to remove any of the fields, and it is also easy to add new values to any of the 4 table variables (to increase the number of possible combinations) as the query dynamically adjusts the randomization range to fit whatever data is in each table variable (i.e. rows 1 - n).

DECLARE @TelNumber TABLE (TelNumberID INT NOT NULL IDENTITY(1, 1),
                          Num VARCHAR(30) NOT NULL);
INSERT INTO @TelNumber (Num) VALUES ('1525407'), ('5423986'), ('1245398'), ('32657891'),
                                    ('123658974'), ('7896534'), ('12354698');

DECLARE @FirstName TABLE (FirstNameID INT NOT NULL IDENTITY(1, 1),
                          Name NVARCHAR(30) NOT NULL);
INSERT INTO @FirstName (Name) VALUES ('Babak'), ('Carolin'), ('Martin'), ('Marie'),
                  ('Susane'), ('Michail'), ('Ramona'), ('Ulf'), ('Dirk'), ('Sebastian');

DECLARE @LastName TABLE (LastNameID INT NOT NULL IDENTITY(1, 1),
                         Name NVARCHAR(30) NOT NULL);
INSERT INTO @LastName (Name) VALUES ('Bastan'), ('Krause'), ('Rosner'),
                  ('Gartenmeister'), ('Rentsch'), ('Benn'), ('Kycik'), ('Leuoth'),
                  ('Kamkar'), ('Kolaee');

DECLARE @Address TABLE (AddressID INT NOT NULL IDENTITY(1, 1),
                        Addr NVARCHAR(100) NOT NULL);
INSERT INTO @Address (Addr) VALUES ('Deutschlan Chemnitz Sonnenstraße 59'), (''),
  ('Deutschland Chemnitz Arthur-Strobel straße 124'),
  ('Deutschland Chemnitz Brückenstraße 3'),
  ('Iran Shiraz Chamran Blvd, Niayesh straße Nr.155'), (''),
  ('Deutschland Berlin Charlotenburg Pudbulesky Alleee 52'),
  ('United State of America Washington DC. Farbod Alle'), ('');

DECLARE @RowsToInsert INT = 10000;

;WITH rowcounts AS
(
  SELECT (SELECT COUNT(*) FROM @TelNumber) AS [TelNumberRows],
         (SELECT COUNT(*) FROM @FirstName) AS [FirstNameRows],
         (SELECT COUNT(*) FROM @LastName) AS [LastNameRows],
         (SELECT COUNT(*) FROM @Address) AS [AddressRows]
), nums AS
(
  SELECT TOP (@RowsToInsert)
         (CRYPT_GEN_RANDOM(1) % rc.TelNumberRows) + 1 AS [RandomTelNumberID],
         (CRYPT_GEN_RANDOM(1) % rc.FirstNameRows) + 1 AS [RandomFirstNameID],
         (CRYPT_GEN_RANDOM(1) % rc.LastNameRows) + 1 AS [RandomLastNameID],
         (CRYPT_GEN_RANDOM(1) % rc.AddressRows) + 1 AS [RandomAddressID]
  FROM   rowcounts rc
  CROSS JOIN msdb.sys.all_columns sac1
  CROSS JOIN msdb.sys.all_columns sac2
)
-- INSERT dbo.Unsprstb(Firstname, Lastname, Tel, Address)
SELECT fn.Name, ln.Name, tn.Num, ad.Addr
FROM   @FirstName fn
FULL JOIN nums
        ON nums.RandomFirstNameID = fn.FirstNameID
FULL JOIN @LastName ln
        ON ln.LastNameID = nums.RandomLastNameID
FULL JOIN @TelNumber tn
        ON tn.TelNumberID = nums.RandomTelNumberID
FULL JOIN @Address ad
        ON ad.AddressID = nums.RandomAddressID;

Notes:

  • The FULL JOINs are needed instead of INNER JOINs to get the entire @RowsToInsert amount of rows.
  • Duplicate rows are possible due to the very nature of this randomization AND not filtering them out by using DISTINCT. However, DISTINCT cannot be used with the given sample data in the question since the number of elements in each array / table variable provide for only 6300 unique combinations and the requested number of rows to generate is 10,000. If more values are added to the table variables such that the total possible unique combinations rises above the requested number of rows, then either the DISTINCT keyword can be added to the nums CTE, or the query can be restructured to simply CROSS JOIN all of the table variable, include a ROW_COUNT() field, and grab the TOP(n) using ORDER BY NEWID() (but that approach has its pros and cons as well).
  • The INSERT is commented out so it is easier to see that the query above produces the desired result. Just uncomment the INSERT to have the query do the actual DML operation.


来源:https://stackoverflow.com/questions/31948717/sql-random-name-generator-not-inserting-first-and-last-name-in-the-same-row

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!