sql insert into, select, where statement - mysql

I want to copy all row from hk_room table into hk_history except row with rStatus = '-' OR rStatus='Long Stay' and rStatus = 'Check Out'.
'-' is the default value for rStatus attribute.
I have tried these two query:
INSERT INTO hk_history
(rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate)
SELECT rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate
FROM hk_room1;
WHERE rStatus <> '-';
or
INSERT INTO hk_history
(rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate)
SELECT rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate
FROM hk_room1;
WHERE rStatus = 'Long Stay' AND rStatus = 'Check Out';
but I got this error

You have a semicolon before the where in the first query:
INSERT INTO hk_history
(rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate)
SELECT rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate
FROM hk_room1;
-------------^
WHERE rStatus <> '-';
You need to remove it.
To achieve this:
want to copy all row from hk_room table into hk_history except row
with rStatus = '-' OR rStatus='Long Stay' and rStatus = 'Check Out'.
Just use a single statement:
INSERT INTO hk_history
(rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate)
SELECT rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate
FROM hk_room1
WHERE NOT (rStatus = '-' OR
rStatus = 'Long Stay' and rStatus = 'Check Out'
);
You can also phrase that as:
WHERE rStatus <> '-' AND
(rStatus <> 'Long Stay' OR rStatus <> 'Check Out')
However, the previous version seems clearer for your intent.

INSERT INTO hk_history
(rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate)
SELECT rNo,rStatus,bs,bq,hk,ds,dq,pc,twl,fm,amt,db,mw,hkR,fo_R,svR,rDate
FROM hk_room1
WHERE rStatus IN ( '-', 'Long Stay' , 'Check Out')
;
This should help

Related

Best way to ignore null values in MYSQL

My data looks like this,
I have multiple values in the Table field with each having its own unique values for the Data field. However, Data values for TableA will be the same format in the table myTable. Same applies to all records in the Table field.
I am using JSON_EXTRACT to get the value in conjunction with CASE statements.
SELECT
CASE
WHEN
Table = 'table A'
THEN
CONCAT_WS('\n','Name: ',
JSON_EXTRACT(Data, '$.name'))
END AS 'tableA',
CASE
WHEN
Table = 'table B'
THEN
CONCAT_WS('\n','Location: ',
JSON_EXTRACT(Data, '$.fieldType'))
END AS 'tableB' from myTable
The problem with this is that I will be getting null values.
I am getting the below results,
I am expecting the below results,
I want to avoid the null values. Is there any other way to extract the data ? I am using MYSQL.
Option one:
Select *
from ( SELECT CASE WHEN Table_c = 'table A' THEN
CONCAT_WS('\n','Name: ', JSON_EXTRACT(data_c, '$.name'))
END AS 'TableA'
from test_t) A,
( SELECT CASE WHEN Table_c = 'table B' THEN
CONCAT_WS('\n','Location: ', JSON_EXTRACT(data_c, '$.fieldType'))
END AS 'TableB'
from test_t) B
where TableA is not null
and TableB is not null
Option two:
SELECT CASE WHEN Table_c = 'table B' THEN
CONCAT_WS('\n','Location: ', JSON_EXTRACT(data_c, '$.fieldType'))
ELSE
CONCAT_WS('\n','Name: ', JSON_EXTRACT(data_c, '$.name'))
END AS 'Data'
, CASE WHEN Table_c = 'table B' THEN
'Table B'
ELSE
'Table A'
END AS 'Table'
from test_t
Here is the demo
Please note that I have changed the names of the table and columns in my demo.
I think you just want conditional aggregation:
SELECT MAX(CASE WHEN Table = 'table A'
THEN CONCAT_WS('\n', 'Name: ', JSON_EXTRACT(Data, '$.name'))
END) AS tableA,
MAX(CASE WHEN Table = 'table B'
THEN CONCAT_WS('\n','Location: ', JSON_EXTRACT(Data, '$.fieldType'))
END) AS tableB
from myTable;
If there could be multiple matches in the JSON, then you might want GROUP_CONCAT() instead:
SELECT GROUP_CONCAT(CASE WHEN Table = 'table A'
THEN CONCAT_WS('\n', 'Name: ', JSON_EXTRACT(Data, '$.name'))
END) AS tableA,
GROUP_CONCAT(CASE WHEN Table = 'table B'
THEN CONCAT_WS('\n','Location: ', JSON_EXTRACT(Data, '$.fieldType'))
END) AS tableB
from myTable;
Note: you have to understand these are not actual null values in database but because your requirement is to read and convert the rows to columns and thus each row in the final result will have null value for all columns other than the corresponding derived one. We can use max on each column (each "CASE" as in your query).
You could try with below,
SELECT MAX(IF(data_type = 'TableA', CONCAT_WS('\n', 'Name: ',
JSON_EXTRACT(data, '$.name'))
, ''))
TableA,
MAX(IF(data_type = 'TableB', CONCAT_WS('\n', 'Location: ',
JSON_EXTRACT(data, '$.fieldType')), ''))
TableB
FROM mytable

mysql multiple values () include, need update based on condition

I need to update the fields on duplicate key if one columns value is equal to soemthing. Right now I have something like this:
INSERT INTO `table` (metric,amount,something1,something2)
VALUES (metric,amount,something1,something2),
(metric,amount,something1,something2),
(metric,amount,something1,something2)
ON DUPLICATE KEY UPDATE
amount = IF (metric = '6', amount = amount + ( '"+amount+"'),'')
ELSEIF (metric = '8' , amount = amount + ( '"+impressions+"') ,'')
ELSEIF (metrtic = '11' , amount = amount + ( '"+impressions+"') ,'');
What am I doing wrong here?
If I understand correctly, you can use UPDATE , self JOIN With CASE WHEN
[DUPLICATE KEY] can fill you want to check DUPLICATE column.
UPDATE `table` r
JOIN (
SELECT Count(*) cnt,[DUPLICATE KEY]
from `table`
group by [DUPLICATE KEY]
) t1 on r.[DUPLICATE KEY] = t1.[DUPLICATE KEY] and t1.cnt > 1
SET r.amount = (CASE WHEN r.metric = '6' THEN r.amount+ ( '"+amount+"'),''
WHEN r.metric = '8' THEN r.amount + ( '"+impressions+"') ,''
WHEN r.metric = '11' THEN r.amount+ ( '"+impressions+"') ,''
ELSE r.amount
END)
What eventually worked for me is:
INSERT INTO `table` (metric,amount,something1,something2)
VALUES (metric,amount,something1,something2),
(metric,amount,something1,something2),
(metric,amount,something1,something2)
ON DUPLICATE KEY UPDATE
metric = VALUES(metric),
amount = amount + VALUES (amount),
modified = NOW(),
something1= VALUES(something1);
Hope this helps anyone in the future.

Doing an Update in SQL, with a CASE WHEN Statement

What I want to know, is it somehow possible to do an update to a table, in a Case statement? Or if there is Some way to do this? I have a button to pull a report (this button goes and calls a stored procedure, and it gets a list of columns and their residing columns).
I basically want to update the table, IF, and only IF, the DateClosed column is NULL AND ClosedBy is null (i.e., the end date was reached, so the campaign is CLOSED).
The way I usually determine if the campaign is closed, is by doing Checks on the start and end date. Ie When EndDate < GetDate() Then "Closed". So obviously that displays correctly, but my database displays null because there was no update.
This is my stored procedure:
ALTER PROCEDURE [dbo].[sp_CampaignStats]
#from DATETIME,
#to DATETIME
AS
SELECT
CampaignName AS 'CAMPAIGN NAME',
CampaignDescription AS 'CAMPAIGN DESCRIPTION',
CASE
WHEN EndDate >= GETDATE() AND StartDate <= GETDATE() THEN 'Active'
WHEN StartDate >= GETDATE() THEN 'Pending'
WHEN CampaignStatus = 4 THEN 'Archived'
ELSE 'Closed'
END as 'CurrentStatus',
CONVERT(VARCHAR(11), StartDate, 106) + ' - ' + CONVERT(VARCHAR(11), EndDate, 106) AS 'CAMPAIGN DATES',
Discount AS 'DISCOUNT',
[Target] AS 'TARGET',
Uptake AS 'UPTAKE',
tc.DateAdded as 'DATE ADDED',
U.FirstName + ' ' + u.LastName As 'ADDED BY',
CASE
WHEN CloseBy IS NULL AND EndDate < GETDATE() AND CloseBy = Null THEN 'System'
WHEN CampaignStatus = 4 THEN 'Archived'
WHEN CloseBy IS not Null THEN UU.FirstName + ' ' + uu.LastName
ELSE 'Not Closed'
END AS 'CLOSED BY',
DateClosed AS 'DATE CLOSED'
FROM
Tbl_Campaign tc
LEFT JOIN
tbl_User U ON Tc.AddedBy = U.UserId
LEFT JOIN
Tbl_User UU ON TC.CloseBy = UU.UserId
WHERE
(startDate >= #from OR enddate <= #to)
AND CampaignStatus IN (1, 2, 3, 4)
So you want to update your table before the SELECT happens?
Try something like this:
UPDATE dbo.Tbl_Campaign
SET -- what do you want to update to what value here????
WHERE
DateClosed IS NULL
AND ClosedBy IS NULL
Or what exactly are you trying to do?? You're still being rather unclear and vague in your question - you're not mentioning WHAT column in WHICH table you want to update to WHAT value if that condition is met.....
SQL only allows one operation per statement. SELECTs only read data, UPDATEs only write data.
If I've understood your problem though, you've got a NULL in an end date field that's preventing you from displaying your button correctly? If that's the case, you could do something like
SELECT
StatusDate =
CASE WHEN EndDate < GETDATE() THEN 'Closed'
WHEN EndDate > GETDATE() THEN 'Open'
WHEN EndDate IS NULL THEN 'End Date not set'
END
FROM
SourceTable
Or, if it was easier in your code, wrap the CASE in an ISNULL or COALESCE function that can be used to fill in the default value.
None of these will update the table on the read, but they'll all stop the NULL from preventing your read returning anything at all.
Seeing your actual code now, what you want is something like this -
ALTER PROCEDURE [dbo].[usp_CampaignStats]
#from DATETIME,
#to DATETIME
AS
SET NOCOUNT ON;
--Make sure any NULLs we need to have been cleaned up
UPDATE Tbl_Campaign
SET <Fields>
WHERE DateClosed IS NULL AND ClosedBy IS NULL
AND (startDate >= #from OR enddate <= #to)
AND CampaignStatus IN (1, 2, 3, 4);
--Now return the data
SELECT
CampaignName AS 'CAMPAIGN NAME',
CampaignDescription AS 'CAMPAIGN DESCRIPTION',
CASE
WHEN EndDate >= GETDATE() AND StartDate <= GETDATE() THEN 'Active'
WHEN StartDate >= GETDATE() THEN 'Pending'
WHEN CampaignStatus = 4 THEN 'Archived'
ELSE 'Closed'
END as 'CurrentStatus',
CONVERT(VARCHAR(11), StartDate, 106) + ' - ' + CONVERT(VARCHAR(11), EndDate, 106) AS 'CAMPAIGN DATES',
Discount AS 'DISCOUNT',
[Target] AS 'TARGET',
Uptake AS 'UPTAKE',
tc.DateAdded as 'DATE ADDED',
U.FirstName + ' ' + u.LastName As 'ADDED BY',
CASE
WHEN CloseBy IS NULL AND EndDate < GETDATE() AND CloseBy = Null THEN 'System'
WHEN CampaignStatus = 4 THEN 'Archived'
WHEN CloseBy IS not Null THEN UU.FirstName + ' ' + uu.LastName
ELSE 'Not Closed'
END AS 'CLOSED BY',
DateClosed AS 'DATE CLOSED'
FROM
Tbl_Campaign tc
LEFT JOIN
tbl_User U ON Tc.AddedBy = U.UserId
LEFT JOIN
Tbl_User UU ON TC.CloseBy = UU.UserId
WHERE
(startDate >= #from OR enddate <= #to)
AND CampaignStatus IN (1, 2, 3, 4);

Error in last line near end

While i Execute a stored procedure I don't know why showing error in last line...
I can't find any error with it
The error is telling
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near '' at
line 60
_
CREATE PROCEDURE `PartyBalanceViewByLedgerId`
(
p_ledgerId varchar(50),
p_crOrDr varchar(50),
p_branchId varchar(50)
)
BEGIN
IF (p_crOrDr='Dr')
THEN
SELECT
TEMP.voucherNo +'_'+ TEMP.voucherType AS ID,
TEMP.voucherType,
CASE WHEN (TEMP.voucherType = 'Receipt Voucher')
THEN
(SELECT receiptMasterId FROM tbl_ReceiptMaster
WHERE (receiptMasterId = TEMP.voucherNo))
ELSE
(SELECT purchaseMasterId FROM tbl_PurchaseMaster
WHERE (purchaseMasterId = TEMP.voucherNo))
END AS voucherNo,
CAST(CAST(TEMP.balance AS DECIMAL(24,2)) AS char(27))
AS amount
FROM(SELECT
A.voucherNo,
A.voucherType,
(SUM(ifnull(A.credit, 0)) - SUM(ifnull(A.debit, 0)))
AS balance
FROM tbl_PartyBalance AS A
WHERE (A.voucherType = 'Purchase Invoice'
OR A.voucherType = 'Receipt Voucher')
AND A.ledgerId=p_ledgerId
AND A.branchId=p_branchId
AND A.optional='False'
GROUP BY A.voucherNo,A.voucherType
)AS TEMP
WHERE TEMP.Balance>0 ;
ELSE
SELECT
TEMP.voucherNo +'_'+ TEMP.voucherType ID,
TEMP.voucherType,
CASE WHEN TEMP.voucherType = 'Payment Voucher' THEN
(SELECT paymentMasterId FROM tbl_PaymentMaster WHERE (paymentMasterId = TEMP.voucherNo))
ELSE
(SELECT salesInvoiceNo FROM tbl_SalesMaster WHERE (salesMasterId = TEMP.voucherNo)) END AS voucherNo,
CAST(CAST(TEMP.balance AS DECIMAL(24,2))AS char(27)) AS amount
FROM(
SELECT
A.voucherNo,
A.voucherType,
(SUM(ifnull(A.debit, 0)) - SUM(ifnull(A.credit,0))) AS balance
FROM tbl_PartyBalance AS A
WHERE (A.voucherType = 'Sales Invoice' OR A.voucherType = 'Payment Voucher'OR A.voucherType = 'Job Invoice') AND A.ledgerId=p_ledgerId AND A.branchId=p_branchId AND A.optional='False'
GROUP BY A.voucherNo,A.voucherType
)AS TEMP
WHERE TEMP.Balance > 0 ;
END
try with this i have update some changes END IF and ; etc
CREATE PROCEDURE `PartyBalanceViewByLedgerId`
(
p_ledgerId varchar(50),
p_crOrDr varchar(50),
p_branchId varchar(50)
)
BEGIN
IF (p_crOrDr='Dr')
SELECT
TEMP.voucherNo +'_'+ TEMP.voucherType AS ID,
TEMP.voucherType,
CASE WHEN (TEMP.voucherType = 'Receipt Voucher')
THEN
(SELECT receiptMasterId FROM tbl_ReceiptMaster
WHERE (receiptMasterId = TEMP.voucherNo))
ELSE
(SELECT purchaseMasterId FROM tbl_PurchaseMaster
WHERE (purchaseMasterId = TEMP.voucherNo))
END AS voucherNo,
CAST(CAST(TEMP.balance AS DECIMAL(24,2)) AS char(27))
AS amount
FROM(SELECT
A.voucherNo,
A.voucherType,
(SUM(ifnull(A.credit, 0)) - SUM(ifnull(A.debit, 0)))
AS balance
FROM tbl_PartyBalance AS A
WHERE (A.voucherType = 'Purchase Invoice'
OR A.voucherType = 'Receipt Voucher')
AND A.ledgerId=p_ledgerId
AND A.branchId=p_branchId
AND A.optional='False'
GROUP BY A.voucherNo,A.voucherType
)AS TEMP
WHERE TEMP.Balance>0;
ELSE
SELECT
TEMP.voucherNo +'_'+ TEMP.voucherType ID,
TEMP.voucherType,
CASE WHEN TEMP.voucherType = 'Payment Voucher' THEN
(SELECT paymentMasterId FROM tbl_PaymentMaster WHERE (paymentMasterId = TEMP.voucherNo))
ELSE
(SELECT salesInvoiceNo FROM tbl_SalesMaster WHERE (salesMasterId = TEMP.voucherNo)) END AS voucherNo,
CAST(CAST(TEMP.balance AS DECIMAL(24,2))AS char(27)) AS amount
FROM(
SELECT
A.voucherNo,
A.voucherType,
(SUM(ifnull(A.debit, 0)) - SUM(ifnull(A.credit,0))) AS balance
FROM tbl_PartyBalance AS A
WHERE (A.voucherType = 'Sales Invoice' OR A.voucherType = 'Payment Voucher'OR A.voucherType = 'Job Invoice') AND A.ledgerId=p_ledgerId AND A.branchId=p_branchId AND A.optional='False'
GROUP BY A.voucherNo,A.voucherType
)AS TEMP
WHERE TEMP.Balance > 0 ;
END IF;
END;
Are you using a DELIMITER? If not pl go through this description:
Delimiters in MySQL
I hope this will solve your problem.
Remove the semicolon before ELSE in :
GROUP BY A.voucherNo,A.voucherType
)AS TEMP
WHERE TEMP.Balance>0
ELSE
SELECT
TEMP.voucherNo +'_'+ TEMP.voucherType ID,
TEMP.voucherType,

MySQL - UPDATE or INSERT if exists

I have a table in a MySQL database that needs to be updated if an instance does not already exist. I have tried the following methods but are no closer to a solution:
SET #last_message_id = (
SELECT id FROM mailbox_last_message WHERE conversationId = '13'
);
BEGIN TRANSACTION;
UPDATE mailbox_last_message SET conversationId = '13', initiatorMessageId = '20', interlocutorMessageId = '10'
WHERE id = #last_message_id
IF (##ROWCOUNT = 0)
INSERT INTO mailbox_last_message ( id , conversationId , initiatorMessageId , interlocutorMessageId )
VALUES ('' , '13', '20', '0' );
COMMIT;
And this one:
SET #last_message_id = (
SELECT `id` FROM mailbox_last_message WHERE `conversationId` = 13);
INSERT INTO mailbox_last_message ( id , conversationId , initiatorMessageId , interlocutorMessageId )
VALUES ( '', '13', '20', '0' ) ON DUPLICATE
KEY UPDATE id = #last_message_id
This solution creates a new instance with conversationId 13 which is not what I want. I've tried to search the documentation and various tutorials/examples online but I can't find any suitable solution. Any help will be greatly appreciated.
If you have a unique index on the fields that you want to keep unique, you can use INSERT IGNORE INTO syntax
SET #last_message_id = (
SELECT id FROM mailbox_last_message WHERE conversationId = '13'
);
INSERT IGNORE INTO mailbox_last_message ( id , conversationId , initiatorMessageId , interlocutorMessageId )
VALUES ('' , '13', '20', '0' ) ON DUPLICATE KEY UPDATE id = #last_message_id;