Clickhouse deleting data with WHERE - sql

I am trying to delete some data using WHERE, note that I need 2 tables in order to identify the rows that should be deleted, so I need to join them, I thought of something like:
ALTER TABLE sample_db.test_first_table DELETE WHERE
(
SELECT s.value
FROM sample_db.test_first_table ft
JOIN sample_db.test_second_table st ON (ft.value=st.value)
WHERE `EXPRESSION HERE`
)
I understood that this Alter operation is a mutation, so when checking system.mutations table I see there is this fail reason: Code: 125, e.displayText() = DB::Exception: Scalar subquery returned more than one row
I checked that the expression I am writing is fine with a simple SELECT statement, so I am out of ideas how I can delete multiple rows based on an expression, any help is much appreciated

First of all: MUTATIONS are admin operations. They cannot be used on daily bases.
ALTER TABLE sample_db.test_first_table DELETE WHERE
value in
( SELECT value
from sample_db.test_second_table
WHERE `EXPRESSION HERE`
)

Related

JOIN of DB table and internal table produces "is not defined in the ABAP Dictionary"

First: I'm working on a existing code and want to add some new stuff to it and I'm really new to ABAP
My goal: I want to duplicate an existing table and remove all values that occur multiple times. That - at least I think - works. Afterwards I want to INNER JOIN this new created table with another already existing table, but unfortunately I always get the following error:
Method MethodName "newCreatedTable" is not defined in the ABAP Dictionary as a table, projection view, or database view
Additional Info: As you can see I'm working inside of a method!
Here is my code what I've done so far:
creating new table and delete all duplicates
DATA newCreatedTable TYPE STANDARD TABLE OF existingTable.
SELECT columnName
FROM existingTable INTO TABLE newCreatedTable.
DELETE ADJACENT DUPLICATES
FROM newCreatedTable COMPARING columnName.
here is where the error happens
SELECT *
FROM anotherExistingTable as p
INNER JOIN newCreatedTable as t on t~columnName = p~columnName
...
I hope someone can help me out in this case! Thank You in advance!
If I'm not wrong your code looks like this:
DATA newCreatedTable TYPE STANDARD TABLE OF existingTable.
SELECT columnName FROM existingTable INTO TABLE newCreatedTable.
DELETE ADJACENT DUPLICATES
FROM newCreatedTable COMPARING columnName.
SELECT *
FROM anotherExistingTable
INNER JOIN newCreatedTable as t on t~columnName = p~columnName
If this is the case then you cannot make a SELECT on an internal table. You can only make this operation on a table that exists in the ABAP dictionary.
Your code should look like this:
DATA newCreatedTable TYPE STANDARD TABLE OF existingTable.
SELECT columnName
FROM existingTable INTO TABLE #newCreatedTable.
DELETE ADJACENT DUPLICATES FROM newCreatedTable COMPARING columnName.
SELECT *
FROM anotherExistingTable
FOR ALL ENTRIES IN #newCreatedTable " <-------------- Use FOR ALL ENTRIES
WHERE columnName = #newCreatedTable-columnName. " <-- in your code

OUTPUT Clause in Sql Server (Transact-SQL)

I Know that OUTPUT Clause can be used in INSERT, UPDATE, DELETE, or MERGE statement. The results of an OUTPUT clause in a INSERT, UPDATE, DELETE, or MERGE statements can be stored into a target table.
But, when i run this query
select * from <Tablename> output
I didn't get any error. The query executed as like select * from tablename with out any error and with same no. of rows
So what is the exact use of output clause in select statement. If any then how it can be used?
I searched for the answer but i couldn't find a answer!!
The query in your question is in the same category of errors as the following (that I have also seen on this site)
SELECT *
FROM T1 NOLOCK
SELECT *
FROM T1
LOOP JOIN T2
ON X = Y
The first one just ends up aliasing T1 AS NOLOCK. The correct syntax for the hint would be (NOLOCK) or ideally WITH(NOLOCK).
The second one aliases T1 AS LOOP. To request a nested loops join the syntax would need to be INNER LOOP JOIN
Similarly in your question it just ends up applying the table alias of OUTPUT to your table.
None of OUTPUT, LOOP, NOLOCK are actually reversed keywords in TSQL so it is valid to use them as a table alias without needing to quote them, e.g. in square brackets.
OUTPUT clause return information about the rows affected by a statement. OUTPUT Clause is used along with INSERT, UPDATE, DELETE, or MERGE statements as you mentioned. The reason it is used is because these statements themselves just return the number of rows effected not the rows effected. Thus the usage of OUTPUT with INSERT, UPDATE, DELETE, or MERGE statements helps the user by returning actual rows effected.
SELECT statement itself returns the rows and SELECT doesn't effect any rows. Thus the usage of OUTPUT clause with SELECT is not required or supported. If you want to store the results of a SELECT statement into a target table use SELECT INTO or the standard INSERT along with the SELECT statement.
EDIT
I guess I misunderstood your question. AS #Martin Smith mentioned its is acting an alias in the SELECT statement you mentioned.
IF OBJECT_ID('tempdelete') IS NOT NULL DROP TABLE tempdelete
GO
IF OBJECT_ID('tempdb..#asd') IS NOT NULL DROP TABLE #asd
GO
CREATE TABLE tempdelete (
name NVARCHAR(100)
)
INSERT INTO tempdelete VALUES ('a'),('b'),('c')
--Creating empty temp table with the same columns as tempdelete
SELECT * INTO #asd FROM tempdelete WHERE 1 = 0
DELETE FROM tempdelete
OUTPUT deleted.* INTO #asd
SELECT * FROM #asd
This is how you can put all the deleted records in to a table. The problem with that is that you have to define the table with all the columns matching the table from which you are deleting. This is how i do it.

Push deleted items into temporary table after MERGE

A simple query on the INTO clause. When i try the below statement, the items get pushed into CustomersBackup2013 whether the table exists or not.
SELECT *
INTO CustomersBackup2013
FROM Customers;
However, when i try using the into clause in a MERGE like
MERGE TargetTable tt
USING SyncTable st on <condition>
.
.
WHEN Not MATCHED BY SOURCE
DELETE
OUTPUT deleted.* INTO #Sometemptable;
I get an error saying invalid object name '#Sometemptable'
Isnt it supposed to create the table if it does not exist? Is there something I am doing wrong.
Is there any way i can modify the clause to push items into #Sometemptable?
No, the table has to exists for the output clause to work.
First create the #temp table and then you can output deleted values in it. Columns in the temp table must match columns from output by ordinal and type.
select into table creates a table if required. it is much like oracle's create table as select. see here select into table
merge only inserts, updates or deletes

Validate Data in SQL Server Table

I am trying to validate the data present in SQL Server table using a stored procedure.
In one of the validation rules, i have to check whether the value of a particular column is present in another table.
Suppose i have a staging table with following columns Cat_ID, Amount, SRC_CDE
I have a 'maintable' with following columns CatID , Cat_Name
I have to validate whether the Cat_ID present in staging table exists in the 'maintable' for each row
I am using the following statement to validate
if((Select count(*) from maintable where CatID= #Cat_id) >0 )
-- Do something if data present
I want to know if there is any better way of doing the above thing other than using a select query for every row.
Can i use some sort of an array where i can fetch all the CatID from maintable and the check instead of using a select query.
Thanks
Using a left join to list all the invalid rows.
select
staging.*
from
staging
left join maintable
on staging.catid=maintable.catid
where maintable.catid is null

SQL: I need to take two fields I get as a result of a SELECT COUNT statement and populate a temp table with them

So I have a table which has a bunch of information and a bunch of records. But there will be one field in particular I care about, in this case #BegAttField# where only a subset of records have it populated. Many of them have the same value as one another as well.
What I need to do is get a count (minus 1) of all duplicates, then populate the first record in the bunch with that count value in a new field. I have another field I call BegProd that will match #BegAttField# for each "first" record.
I'm just stuck as to how to make this happen. I may have been on the right path, but who knows. The SELECT statement gets me two fields and as many records as their are unique #BegAttField#'s. But once I have them, I haven't been able to work with them.
Here's my whole set of code, trying to use a temporary table and SELECT INTO to try and populate it. (Note: the fields with # around the names are variables for this 3rd party app)
CREATE TABLE #temp (AttCount int, BegProd varchar(255))
SELECT COUNT(d.[#BegAttField#])-1 AS AttCount, d.[#BegAttField#] AS BegProd
INTO [#temp] FROM [Document] d
WHERE d.[#BegAttField#] IS NOT NULL GROUP BY [#BegAttField#]
UPDATE [Document] d SET d.[#NumAttach#] =
SELECT t.[AttCount] FROM [#temp] t INNER JOIN [Document] d1
WHERE t.[BegProd] = d1.[#BegAttField#]
DROP TABLE #temp
Unfortunately I'm running this script through a 3rd party database application that uses SQL as its back-end. So the errors I get are simply: "There is already an object named '#temp' in the database. Incorrect syntax near the keyword 'WHERE'. "
Comment out the CREATE TABLE statement. The SELECT INTO creates that #temp table.