I would like to eliminate duplication based on company id.
I dont care which of the records under the model name will be deleted / stay.
I have this results:
+------------+------------------+
| company id | model name |
+------------+------------------+
| 1 | chevrolet camaro |
| 1 | chevrolet spark |
| 1 | chevrolet cruze |
| 2 | mercedes c class |
| 2 | mercedes E class |
+------------+------------------+
And I would like to get these results:
+------------+------------------+
| company id | model name |
+------------+------------------+
| 1 | chevrolet camaro |
| 2 | mercedes c class |
+------------+------------------+
Or these results(The point is I don't care which of the model name will be eliminated):
+------------+------------------+
| company id | model name |
+------------+------------------+
| 1 | chevrolet spark |
| 2 | mercedes E class |
+------------+------------------+
What should I do?
You can use a group by:
select companyid, min(modelname) as modelname
from t
group b companyid;
Try this
ALTER IGNORE TABLE 'yourTableName' ADD UNIQUE ('company id');
reference : here
I would try this approach:
declare #tbl table (ID int, car nvarchar(100))
declare #tblTemp table (ID int, car nvarchar(100))
insert into #tbl(ID, car)
values
( 1 ,'chevrolet camaro'),
(1 ,'chevrolet spark'),
(1 ,'chevrolet cruze'),
(2 ,'mercedes c class'),
(2 ,'mercedes E class'),
(1 ,'chevrolet camaro'),
(1 ,'chevrolet spark'),
(1 ,'chevrolet cruze'),
(2 ,'mercedes c class'),
(2 ,'mercedes E class')
insert into #tblTemp
select distinct MAX(id), car from #tbl
group by car
delete from #tbl
insert into #tbl (car)
select car from #tblTemp
declare #i int
SELECT #i= ISNULL(MAX(id),0) FROM #tbl
update #tbl
set id = #i , #i = #i + 1
where id is null
select * from #tbl
SQL result:
Related
I'm validating following SQL approach from the community where I'm completely updating the user's roles. (Full update of the join table)
User
+----+-------+------+
| id | first | last |
+----+-------+------+
| 1 | John | Doe |
| 2 | Jane | Doe |
+----+-------+------+
Role
+----+----------+
| id | name |
+----+----------+
| 1 | admin |
| 2 | accounts |
| 3 | sales |
+----+----------+
UserRole
+--------+--------+
| userid | roleid |
+--------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
| 2 | 3 |
+--------+--------+
My SQL approach -> first delete all, second insert all records
DELETE FROM UserRole WHERE userid = 1;
INSERT INTO UserRole(userid, roleid) VALUES(1, 2), (1, 3);
Is there a better way? I mean to do this in a single query possibly for these sorts of linking/join tables?
Edit
I think what I should have said to find an efficient SQL operation instead of a single query.
Here's another SQL
DELETE FROM UserRole WHERE user_id = 1 AND role_id NOT IN (2, 3);
INSERT INTO UserRole(user_id, role_id) VALUES(1, 2), (1, 3)
ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), role_id = VALUES(role_id);
If you want to add all roles for all users into the userRoles table, you can delete from userRoles, then recreate table like below:
DECLARE #users TABLE ( userID INT, UserName NVARCHAR(MAX) )
DECLARE #roles TABLE ( roleID INT, RoleName NVARCHAR(MAX) )
DECLARE #userRoles TABLE ( userID INT, roleID INT )
INSERT INTO #users (userID,UserName) VALUES (1,'name1'),(2,'name2'),(3,'name3')
INSERT INTO #roles (roleID,RoleName) VALUES (1,'admin'),(2,'accounts'),(3,'sales')
INSERT INTO #userRoles (userID,roleID)
SELECT U.userID,R.roleID FROM #users U
FULL OUTER JOIN #roles R ON 1=1
ORDER BY userID
SELECT * FROM #userRoles
OUTPUT:
userID roleID
1 1
2 1
3 1
1 2
2 2
3 2
1 3
2 3
3 3
I have 2 tables.
This is my GroupTable.
CREATE TABLE GroupTable(
ID INT,
GROUPNAME VARCHAR(50),
UnderGroupId INT
);
INSERT INTO GroupTable VALUES (1,'A',0);
INSERT INTO GroupTable VALUES (2,'B',1);
INSERT INTO GroupTable VALUES (3,'C',2);
INSERT INTO GroupTable VALUES (4,'D',3);
Below is the datatable where i'm passing groupId in data table for reference
CREATE TABLE Reference(
ID INT,
GROUPID VARCHAR(50),
GroupValue VARCHAR(50)
);
INSERT INTO Reference VALUES (1,3,'X');
INSERT INTO Reference VALUES (2,4,'Y');
INSERT INTO Reference VALUES (3,1,'Z');
and i want to show the result like this
| ID | GROUPID | GroupValue | GROUPNAME1 | GROUPNAME2 | GROUPNAME3 | GROUPNAME4 |
|----|---------|------------|------------|------------|------------|------------|
| 1 | 3 | X | A | B | C | |
| 2 | 4 | Y | A | B | C | D |
| 3 | 1 | Z | A | | | |
From your comment, you can try to OUTER JOIN by GROUPID > UnderGroupId condition because that condition is those two table relationship condition.
then
UnderGroupId = 0 mean the group1
UnderGroupId = 1 mean the group2
UnderGroupId = 2 mean the group3
UnderGroupId = 3 mean the group4
You can do condition aggregate function on UnderGroupId, to get the pivot result.
TestDLL
CREATE TABLE GroupTable(
ID INT,
GROUPNAME VARCHAR(50),
UnderGroupId INT
);
INSERT INTO GroupTable VALUES (1,'A',0);
INSERT INTO GroupTable VALUES (2,'B',1);
INSERT INTO GroupTable VALUES (3,'C',2);
INSERT INTO GroupTable VALUES (4,'D',3);
CREATE TABLE Reference(
ID INT,
GROUPID VARCHAR(50),
GroupValue VARCHAR(50)
);
INSERT INTO Reference VALUES (1,3,'X');
INSERT INTO Reference VALUES (2,4,'Y');
INSERT INTO Reference VALUES (3,1,'Z');
Query 1:
SELECT t1.ID,
t1.GROUPID,
t1.GroupValue,
coalesce(MAX(CASE WHEN UnderGroupId = 0 THEN tt.GROUPNAME end),'') GROUPNAME1,
coalesce(MAX(CASE WHEN UnderGroupId = 1 THEN tt.GROUPNAME end),'') GROUPNAME2,
coalesce(MAX(CASE WHEN UnderGroupId = 2 THEN tt.GROUPNAME end),'') GROUPNAME3,
coalesce(MAX(CASE WHEN UnderGroupId = 3 THEN tt.GROUPNAME end),'') GROUPNAME4
FROM Reference t1
LEFT JOIN GroupTable tt ON t1.GROUPID > tt.UnderGroupId
GROUP BY t1.ID,
t1.GROUPID,
t1.GroupValue
Results:
| ID | GROUPID | GroupValue | GROUPNAME1 | GROUPNAME2 | GROUPNAME3 | GROUPNAME4 |
|----|---------|------------|------------|------------|------------|------------|
| 1 | 3 | X | A | B | C | |
| 2 | 4 | Y | A | B | C | D |
| 3 | 1 | Z | A | | | |
I'm trying to make a report of financial datas for my company:
I have actually two two tables:
___BillableDatas:
|--------|------------|----------|----------|--------------|---------------------|
| BIL_Id | BIL_Date | BIL_Type | BIL_Rate | BIL_Quantity | BIL_ApplicableTaxes |
|--------|------------|----------|----------|--------------|---------------------|
| 1 | 2017-01-01 | Night | 95 | 1 | 1 |
| 2 | 2017-01-02 | Night | 95 | 1 | 1 |
| 3 | 2017-01-15 | Night | 105 | 1 | 1 |
| 4 | 2017-01-15 | Item | 8 | 2 | 1,2 |
| 5 | 2017-02-14 | Night | 95 | 1 | 1 |
| 6 | 2017-02-15 | Night | 95 | 1 | 1 |
| 7 | 2017-02-16 | Night | 95 | 1 | 1 |
| 8 | 2017-03-20 | Night | 89 | 1 | 1 |
| 9 | 2017-03-21 | Night | 89 | 1 | 1 |
| 10 | 2017-03-21 | Item | 8 | 3 | 1,2 |
|--------|------------|----------|----------|--------------|---------------------|
___SalesTaxes:
|--------|------------|
| STX_Id | STX_Amount |
|--------|------------|
| 1 | 14.00 |
| 2 | 5.00 |
|--------|------------|
I need to know for each month the sum of my revenue with and without taxes.
Actually I can make the report but don't know how to loop into the ___SalesTaxes table.
What I have actually:
SELECT month(BIL_Date) AS month,
sum(BIL_Rate * BIL_Quantity) AS sumval
FROM `___BillableDatas`
WHERE BIL_Date BETWEEN "2017-01-01" AND "2017-12-31"
AND BIL_Type = "Night" OR BIL_Type = "Item"
GROUP BY year(BIL_Date), month(BIL_Date)
Thanks for your help.
as kbball mentioned you have an unresolved many to many relationship in your main table. A proper table should never be designed to have more than one value per field. Resolving many to many relationships is quite simple. You will need to create a new table something like bill_taxType or some relation like that. The new table would have two fields as well as the standard primary key, it will have bill_id and applicable tax id. In the case of your 1,2 fields like bill id 4 in the new table it will look like
primary key, bill id, applicable tax id
1 4 1
2 4 2
In your final query you will join all three together on the appropriate primary key-foreign key relationship. This final query should have the data that you need.
This will work, I've created following example will help you lot for debugging and implementation. try to implement as below :
If(OBJECT_ID('tempdb..#___BillableDatas') Is Not Null)
Begin
Drop Table #___BillableDatas
End
If(OBJECT_ID('tempdb..#___SalesTaxes') Is Not Null)
Begin
Drop Table #___SalesTaxes
End
CREATE TABLE #___BillableDatas
(
BIL_Id INT IDENTITY (1,1),
BIL_Date DATETIME,
BIL_Type VARCHAR(50),
BIL_Rate FLOAT,
BIL_Quantity INT,
BIL_ApplicableTaxes VARCHAR(10)
);
INSERT INTO #___BillableDatas (BIL_Date,BIL_Type,BIL_Rate,BIL_Quantity,BIL_ApplicableTaxes)
VALUES ('2017-01-01','Night',95,1,'1'),
('2017-01-02','Night',95,1,'1'),
('2017-01-15','Night',105,1,'1'),
('2017-01-15','Item',8,2,'1,2'),
('2017-02-14','Night',95,1,'1'),
('2017-02-15','Night',95,1,'1'),
('2017-02-16','Night',95,1,'1'),
('2017-03-20','Night',89,1,'1'),
('2017-03-21','Night',89,1,'1'),
('2017-03-21','Item',8,1,'1,2')
CREATE TABLE #___SalesTaxes
(
STX_Id INT IDENTITY (1,1),
STX_Amount FLOAT
);
INSERT INTO #___SalesTaxes (STX_Amount) VALUES (14.00),(5.00)
-----------------------------------------------------------------
SELECT * FROM #___BillableDatas
SELECT * FROM #___SalesTaxes
SELECT MONTH(BD.BIL_Date) AS [Month],SUM(BD.BIL_Rate * BD.BIL_Quantity) AS 'Without Tax'
,(SUM(BD.BIL_Rate * BD.BIL_Quantity)+((SUM(BD.BIL_Rate * BD.BIL_Quantity)/100)*BD.Tax1)) AS 'With Tax 1'
,(SUM(BD.BIL_Rate * BD.BIL_Quantity)+((SUM(BD.BIL_Rate * BD.BIL_Quantity)/100)*BD.Tax2)) AS 'With Tax 2'
FROM
(
SELECT *,
(SELECT ST1.STX_Amount FROM Func_Split(BIL_ApplicableTaxes,',') AS F LEFT JOIN #___SalesTaxes AS ST1 ON F.Element=ST1.STX_Id WHERE F.Element='1') AS Tax1 ,
(SELECT ST1.STX_Amount FROM Func_Split(BIL_ApplicableTaxes,',') AS F LEFT JOIN #___SalesTaxes AS ST1 ON F.Element=ST1.STX_Id WHERE F.Element='2') AS Tax2
FROM #___BillableDatas) AS BD
WHERE BD.BIL_Date BETWEEN '2017-01-01' AND '2017-12-31' AND BD.BIL_Type = 'Night' OR BD.BIL_Type = 'Item'
GROUP BY YEAR(BD.BIL_Date), MONTH(BD.BIL_Date),BD.Tax1,BD.Tax2
You will require function Func_Split for above solution, use this :
CREATE FUNCTION [dbo].[func_Split]
(
#DelimitedString varchar(8000),
#Delimiter varchar(100)
)
RETURNS #tblArray TABLE
(
ElementID int IDENTITY(1,1), -- Array index
Element varchar(1000) -- Array element contents
)
AS
BEGIN
-- Local Variable Declarations
-- ---------------------------
DECLARE #Index smallint,
#Start smallint,
#DelSize smallint
SET #DelSize = LEN(#Delimiter)
-- Loop through source string and add elements to destination table array
-- ----------------------------------------------------------------------
WHILE LEN(#DelimitedString) > 0
BEGIN
SET #Index = CHARINDEX(#Delimiter, #DelimitedString)
IF #Index = 0
BEGIN
INSERT INTO
#tblArray
(Element)
VALUES
(LTRIM(RTRIM(#DelimitedString)))
BREAK
END
ELSE
BEGIN
INSERT INTO
#tblArray
(Element)
VALUES
(LTRIM(RTRIM(SUBSTRING(#DelimitedString, 1,#Index - 1))))
SET #Start = #Index + #DelSize
SET #DelimitedString = SUBSTRING(#DelimitedString, #Start , LEN(#DelimitedString) - #Start + 1)
END
END
RETURN
END
I have 3 tables: ak_class, ak_objects, ak_class_object
ak_class:
class_id | class_description | class_name |
1 | some description | some name |
2 | some description | some name |
3 | some description | some name |
ak_objects:
object_id | object_description | object_name |
1 | some description | some name |
2 | some description | some name |
3 | some description | some name |
ak_class_object:
class_object_id | class_id | object_id |
1 | 1 | 1 |
2 | 2 | 2 |
3 | 3 | 3 |
I need to fill in the ak_class_object with a class_id from ak_class table and object_id from ak_objects table.
The question is how can I update (I need to update as there is some wrong data currently) the class_id from the ak_class table with all the ids? I was thinking of using it with JOIN ut I don't know which id to use to Join them as class_id is only to be updated
UPD: I was trying to do it like this, but it didn't work:
DELIMITER $$
DROP PROCEDURE class_object_1$$
CREATE PROCEDURE class_object_1()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE (i < 250000) DO
UPDATE ak_class_object
SET class_id = SELECT DISTINCT class_id from ak_class, object_id = SELECT DISTINCT class_id from ak_objects;
SET i = i + 1;
END WHILE;
END$$
I am writing the generic syntax, change the table names and column name as per your requirements.
update table1 inner join table2
on table1.id = table2.fk_id
set table1.column = table1.columnUpdated
Hi I need to be able to join two tables and return the second table
as columns to the first table. I need to create
(dependent first name, dependent last name, and dependent relationship)
based on the max number depid (which can be dynamic).
thank you in advance
table 1
+-------------+-------------+------------+
| employeeid | first name | last name |
+-------------+-------------+------------+
| 1 | bill | johnson |
| 2 | matt | smith |
| 3 | katy | lewis |
+-------------+-------------+------------+
table 2
+-------------------------------------------------------------------+
| employeeid |dependent id | First Name | Last Name | Relationship |
+-------------------------------------------------------------------+
| 1 1 mary johnson spouse |
| 1 2 aaron johnson child |
| 2 1 eric smith child |
+-------------------------------------------------------------------+
expected output
+------------+------------+-----------+----------------------+---------------------+------------------------+----------------------+---------------------+------------------------+
| employeeid | first name | last name | dependent first name | dependent last name | dependent relationship | dependent first name | dependent last name | dependent relationship |
+------------+------------+-----------+----------------------+---------------------+------------------------+----------------------+---------------------+------------------------+
| 1 | bill | johnson | mary | johnson | spouse | aaron | johnson | child |
| 2 | matt | smith | eric | smith | child | | | |
| 3 | katty | lewis | | | | | | |
+------------+------------+-----------+----------------------+---------------------+------------------------+----------------------+---------------------+------------------------+
You Can do This with dynamic SQL & XML Path example SQL below
--Table 1
CREATE TABLE #TMP1 (EMP_ID INT, NAME Char(10) )
INSERT INTO #TMP1 VALUES (1,'One')
INSERT INTO #TMP1 VALUES (2,'TWO')
INSERT INTO #TMP1 VALUES (3,'Three')
--Table 2
CREATE TABLE #TMP2 (EMP_ID INT, DP_ID INT,FNAME Char(10),Rel Char(10) )
INSERT INTO #TMP2 VALUES (1,1,'Spouse One','Spouse')
INSERT INTO #TMP2 VALUES (1,2,'Child One','Child')
INSERT INTO #TMP2 VALUES (2,1,'Child TWO','Child')
Declare #CNT Int
, #Ctr int = 0
, #SQL VarChar(MAX)
--Get Max Dependent ID
SELECT #CNT = MAX(DP_ID) from #TMP2
--For Verification
SELECT #CNT
--Build Dynamic SQL to get the dataset
SET #SQL = 'SELECT Emp_ID '
While #Ctr < #CNT
Begin
Set #Ctr = #Ctr+1
SET #SQL = #SQL + ', ( SELECT FName+'+''''+''''+' FROM #TMP2 Where #TMP1.EMP_ID = #TMP2.EMP_ID and #TMP2.DP_ID = '+Convert(VarChar(2),#Ctr)+' For XML Path ('+''''+''''+') ) as FName'+Convert(VarChar(2),#Ctr)
SET #SQL = #SQL + ', ( SELECT Rel+'+''''+''''+' FROM #TMP2 Where #TMP1.EMP_ID = #TMP2.EMP_ID and #TMP2.DP_ID = '+Convert(VarChar(2),#Ctr)+' FOR XML Path ('+''''+''''+') ) as Rel'+Convert(VarChar(2),#Ctr)
End
SET #SQL = #SQL+' FROM #TMP1 '
--For Verification Print the Dynamic SQL
Select #SQL
--Execute the dynamic SQL
EXEC(#SQL)