Вы можете попробовать использовать PIVOT в SQL Server, возможно, он вам подойдет.
CREATE TABLE #items (
ID_item int,
name varchar(20)
)
CREATE TABLE #item_location (
ID_item int,
ID_location char(1)
)
INSERT INTO #items( ID_item, name ) VALUES (1,'Mouse')
INSERT INTO #items( ID_item, name ) VALUES (2,'Keyboard')
INSERT INTO #items( ID_item, name ) VALUES (3,'Speaker')
INSERT INTO #item_location (ID_item, ID_location) VALUES (1,'A')
INSERT INTO #item_location (ID_item, ID_location) VALUES (1,'B')
INSERT INTO #item_location (ID_item, ID_location) VALUES (1,'C')
INSERT INTO #item_location (ID_item, ID_location) VALUES (1,'D')
INSERT INTO #item_location (ID_item, ID_location) VALUES (2,'A')
INSERT INTO #item_location (ID_item, ID_location) VALUES (2,'C')
INSERT INTO #item_location (ID_item, ID_location) VALUES (3,'A')
INSERT INTO #item_location (ID_item, ID_location) VALUES (3,'B')
INSERT INTO #item_location (ID_item, ID_location) VALUES (3,'C')
--SELECT B.ID_location, COUNT(1)
--FROM #items AS A
--INNER JOIN #item_location AS B ON A.ID_item = B.ID_Item
--GROUP BY B.ID_Location;
DECLARE @sql NVARCHAR(max);
DECLARE @columns VARCHAR(200);
SET @columns = STUFF(
(
SELECT
','+ QUOTENAME(LTRIM(name))
FROM
(SELECT DISTINCT
A.name
FROM #items AS A
) AS T
FOR XML PATH('')
), 1, 1, '')
SET @sql = N'
SELECT
*
FROM
(
SELECT ID_location,name
FROM #item_location A INNER JOIN #items B ON B.ID_item = A.ID_item
) AS T
PIVOT
(
count(name)
FOR name IN (' + @columns + N')
) AS P order by ID_location;';
EXEC sp_executesql @sql;
DROP TABLE #item_location
DROP TABLE #items