There's a lot to unpack here. Let's start with how to present demo data:
If you provide the DDL and DML for your data it makes it much easier for folks to work with:
DECLARE @Customer TABLE (ID INT, Name NVARCHAR(100))
DECLARE @Detail TABLE (ID INT, Name NVARCHAR(20))
DECLARE @DataValues TABLE (CustomerID INT, DetailID INT, [Values] NVARCHAR(20))
INSERT INTO @Customer (ID, Name) VALUES
(1, 'Jack'),(2, 'Anne')
INSERT INTO @Detail (ID, Name) VALUES
(1, 'Sex'),(2, 'Age')
INSERT INTO @DataValues (CustomerID, DetailID, [Values]) VALUES
(1, 1, 'M'),(1, 2, '30'),(2, 1, 'F'),(2, 2, '28')
This sets up your tables (as variables) and populates them with the demo data.
Next let's talk about the horrible schema here.
You should always to try avoid reserved words as column names too. Values
is a keyword.
This should probably be a single customers table:
DECLARE @Genders TABLE (ID INT IDENTITY, Name NVARCHAR(20))
DECLARE @Customer1 TABLE (CustomerID INT IDENTITY, Name NVARCHAR(100), BirthDate DATETIME, GenderID INT NULL, Age AS (DATEDIFF(YEAR, BirthDate, CURRENT_TIMESTAMP)))
Notice I used BirthDate instead of Age. This is because a persons age will change over time, but their birth date will not. Attributes that are calculated based on another attribute shouldn't be stored (but if you want you can used a calculated column, as we are here). You'll also note that instead of explicitly defining gender in the customers table we instead will reference it by Gender ID. This is a lookup table.
If you had used a normalized schema your query would then look like:
/* Demo Data */
DECLARE @Genders TABLE (ID INT IDENTITY, Name NVARCHAR(20));
INSERT INTO @Genders (Name) VALUES
('Male'),('Female'),('Non-Binary');
DECLARE @Customer1 TABLE (CustomerID INT IDENTITY, Name NVARCHAR(100), BirthDate DATETIME, GenderID INT NULL, Age AS (DATEDIFF(YEAR, BirthDate, CURRENT_TIMESTAMP)));
INSERT INTO @Customer1 (Name, BirthDate, GenderID) VALUES
('Jack', '2000-11-03', 1),('Anne', '2000-11-01', 2),('Chris', '2001-05-13', NULL);
/* Query */
SELECT *
FROM @Customer1 c
LEFT OUTER JOIN @Genders g
ON c.GenderID = g.ID;
Now on to how to get the data you want from the structure you have. Anyway you do this is going to be acrobatic because we have to work against the schema.
/* Demo Data */
DECLARE @Customer TABLE (ID INT, Name NVARCHAR(100));
DECLARE @Detail TABLE (ID INT, Name NVARCHAR(20));
DECLARE @DataValues TABLE (CustomerID INT, DetailID INT, [Values] NVARCHAR(20));
INSERT INTO @Customer (ID, Name) VALUES
(1, 'Jack'),(2, 'Anne');
INSERT INTO @Detail (ID, Name) VALUES
(1, 'Sex'),(2, 'Age');
INSERT INTO @DataValues (CustomerID, DetailID, [Values]) VALUES
(1, 1, 'M'),(1, 2, '30'),(2, 1, 'F'),(2, 2, '28');
/* Query */
SELECT *
FROM (
SELECT d.Name AS DetailName, c.Name AS CustomerName, DV.[Values]
FROM @DataValues dv
INNER JOIN @Detail d
ON dv.DetailID = d.ID
INNER JOIN @Customer c
ON dv.CustomerID = c.ID
) a
PIVOT (
MAX([Values]) FOR DetailName IN (Sex,Age)
) p;
CustomerName Sex Age
-----------------------
Anne F 28
Jack M 30