SQL SERVER merge two column, combine it, and count the same - asp.net

I want to create a barcode by merge and combine two column.
here is my table :
ID | Items1 | Items2 | BArcode
001 | Shirt | CPU |
002 | Shirt | CPU |
001 | Shoes | Monitor |
002 | Jacket | Monitor |
001 | Shoes | CPU |
002 | | Keyboard |
002 | | Keyboard |
001 | Shirt | Keyboard |
002 | Shirt | |
The barcode created based on ID+Item1/Items2+Count. The count get from counting how many times one ID have oredered the same item. I want it to display only the data that haven't generated a barcode, so it's when the Barcode column value is null, from the above table the Barcode is null:
ID | Barcode |
001 | 001Shirt1 |
002 | 002Shirt1 |
001 | 001Shoes1 |
002 | 002Jacket1 |
001 | 001Shoes2 |
001 | 001Shirt2 |
002 | 002Shirt2 |
001 | 001CPU1 |
002 | 002CPU1 |
001 | 001Monitor1 |
002 | 002Monitor1 |
001 | 001CPU2 |
002 | 002Keyboard1 |
002 | 002Keyboard2 |
001 | 001Keyboard1 |
here is my first code :
Dim strcommand As String = "select [ID], ([ID] + [Items1])
as Barcode from tbl_Request where [Items1] != 'null'
and Barcode = 'null' union select ([ID] + [Items2])
from tbl_Request where [Items2] != 'Null' and Barcode = 'null'"
it doesn't work. it say "All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists". on my code above I haven't implement the counting yet. does anyone know how to do it?
Thanks in advances....

You can use this query to generate the barcode values:
;with cte as
(select id, item1 item, row_number() over (partition by id, item1 order by getdate()) rn
from items
where item1 is not null and barcode is null
union
select id, item2 item, row_number() over (partition by id, item2 order by getdate()) rn
from items
where item2 is not null and barcode is null)
select id, cast(id as varchar) + item + cast(rn as varchar) barcode
from cte
If you wanted to add this to a new table, say tbl_barcode with columns id and barcode, you would do this:
;with cte as
(select id, item1 item, row_number() over (partition by id, item1 order by getdate()) rn
from items
where item1 is not null and barcode is null
union
select id, item2 item, row_number() over (partition by id, item2 order by getdate()) rn
from items
where item2 is not null and barcode is null)
insert into tbl_barcode (id, barcode)
select id, cast(id as varchar) + item + cast(rn as varchar) barcode
from cte

The error that you are getting is that the union join that you have created does not contain the same fields in the second select statement, as your original select statement. SQL UNION Operator, Notice that each SELECT statement within the UNION must have the same number of columns.
So therefore you will need to change
select ([ID] + [Items2])
to
select [ID], ([ID] + [Items2])

declare #x table (ID varchar(20),Items1 VARCHAR(10),Items2 VARCHAR(10),BARCODE INT)
INSERT INTO #x
(ID,Items1,Items2,BARCODE)
VALUES ('001','Shirt','CPU',NULL)
INSERT INTO #x
(ID,Items1,Items2,BARCODE)
VALUES ('001',NULL,'Monitor',NULL)
INSERT INTO #x
(ID,Items1,Items2,BARCODE)
VALUES ('002','TRouser','Monitor',NULL)
select ID,
Case when Items1 IS NOT NULL Then ID +Items1+
CAST(DENSE_RANK()OVER(PARTITION by Items1 order by Items1 desc)AS VARCHAR)
when Items2 IS NOT NULL Then ID +Items2+
CAST(DENSE_RANK()OVER(PARTITION by Items2 order by Items1 desc)AS VARCHAR)
ELSE '' END AS Barcode from #x

Related

How can I set multiple aliases for a single derived table in MariaDB 5.5?

Consider a database with three tables:
goods (Id is the primary key)
+----+-------+-----+
| Id | Name | SKU |
+----+-------+-----+
| 1 | Nails | 123 |
| 2 | Nuts | 456 |
| 3 | Bolts | 789 |
+----+-------+-----+
invoiceheader (Id is the primary key)
+----+--------------+-----------+---------+
| Id | Date | Warehouse | BuyerId |
+----+--------------+-----------+---------+
| 1 | '2021-10-15' | 1 | 223 |
| 2 | '2021-09-18' | 1 | 356 |
| 3 | '2021-07-13' | 2 | 1 |
+----+--------------+-----------+---------+
invoiceitems (Id is the primary key)
+----+----------+--------+-----+-------+
| Id | HeaderId | GoodId | Qty | Price |
+----+----------+--------+-----+-------+
| 1 | 1 | 1 | 15 | 1.1 |
| 2 | 1 | 3 | 7 | 1.5 |
| 3 | 2 | 1 | 12 | 1.5 |
| 4 | 3 | 3 | 3 | 1.3 |
+----+----------+--------+-----+-------+
What I'm trying to do is to get the MAX(invoiceheader.Date) for every invoiceitems.GoodId. Or, in everyday terms, to find out, preferably in a single query, when was the last time any of the goods were sold, from a specific warehouse.
To do that, I'm using a derived query, and the solution proposed here . In order to be able to do that, I think that I need to have a way of giving multiple (well, two) aliases for a derived table.
My query looks like this at the moment:
SELECT tmp.* /* placing the second alias here, before or after tmp.* doesn't work */
FROM ( /* placing the second alias, tmpClone, here also doesn't work */
SELECT
invoiceheader.Id,
invoiceheader.Date,
invoiceitems.HeaderId,
invoiceitems.Id,
invoiceitems.GoodId
FROM invoiceheader
LEFT JOIN invoiceitems
ON invoiceheader.Id = invoiceitems.HeaderId
WHERE invoiceheader.Warehouse = 3
AND invoiceheader.Date > '0000-00-00 00:00:00'
AND invoiceheader.Date IS NOT NULL
AND invoiceheader.Date > ''
AND invoiceitems.GoodId > 0
ORDER BY
invoiceitems.GoodId ASC,
invoiceheader.Date DESC
) tmp, tmpClone /* this doesn't work with or without a comma */
INNER JOIN (
SELECT
invoiceheader.Id,
MAX(invoiceheader.Date) AS maxDate
FROM tmpClone
WHERE invoiceheader.Warehouse = 3
GROUP BY invoiceitems.GoodId
) headerGroup
ON tmp.Id = headerGroup.Id
AND tmp.Date = headerGroup.maxDate
AND tmp.HeaderId = headerGroup.Id
Is it possible to set multiple aliases for a single derived table? If it is, how should I do it?
I'm using 5.5.52-MariaDB.
you can use both (inner select) and left join to achieve this for example:
select t1.b,(select t2.b from table2 as t2 where t1.x=t2.x) as 'Y' from table as t1 Where t1.y=(select t3.y from table3 as t3 where t2.a=t3.a)
While this doesn't answer my original question, it does solve the problem from which the question arose, and I'll leave it here in case anyone ever comes across a similar issue.
The following query does what I'd intended to do - find the newest sale date for the goods from the specific warehouse.
SELECT
invoiceheader.Id,
invoiceheader.Date,
invoiceitems.HeaderId,
invoiceitems.Id,
invoiceitems.GoodId
FROM invoiceheader
INNER JOIN invoiceitems
ON invoiceheader.Id = invoiceitems.HeaderId
INNER JOIN (
SELECT
MAX(invoiceheader.Date) AS maxDate,
invoiceitems.GoodId
FROM invoiceheader
INNER JOIN invoiceitems
ON invoiceheader.Id = invoiceitems.HeaderId
WHERE invoiceheader.Warehouse = 3
AND invoiceheader.Date > '0000-00-00 00:00:00'
AND invoiceheader.Date IS NOT NULL
AND invoiceheader.Date > ''
GROUP BY invoiceitems.GoodId
) tmpDate
ON invoiceheader.Date = tmpDate.maxDate
AND invoiceitems.GoodId = tmpDate.GoodId
WHERE invoiceheader.Warehouse = 3
AND invoiceitems.GoodId > 0
ORDER BY
invoiceitems.GoodId ASC,
invoiceheader.Date DESC
The trick was to join by taking into consideration two things - MAX(invoiceheader.Date) and invoiceitems.GoodId - since one GoodId can only appear once inside a specific invoiceheader / invoiceitems JOINing (strict limit imposed on the part of the code which inserts into invoiceitems).
Whether this is the most optimal solution (ignoring the redundant conditions in the query), and whether it would scale well, remains to be seen - it has been tested on tables with ~5000 entries for invoiceheader, ~60000 entries for invoiceitems, and ~4000 entries for goods. Execution time was < 1 sec.

SQLite Select with join from the same parent

I have two simple tables:
Names:
+----+-------------+
| id | Name |
+----+-------------+
| 1 | John Smith |
| 2 | Joe Doe |
+----+-------------+
Relations:
+----+----------+---------+
| id | ParentID | ChildID |
+----+----------+---------+
| 1 | 1 | 2 |
+----+----------+---------+
The table relation, Parent is Foreign Key to Names and Child is Foreign Key to Names.
Is there a way to SELECT and replace ParentID and ChildID with Name from Names where number matches Names.id?
You can join with the same table multiple times, as long as you give each instance a unique name:
SELECT Parent.Name,
Child.Name
FROM Relations
JOIN Names AS Parent ON Relations.ParentID = Parent.ID
JOIN Names AS Child ON Relations.ChildID = Child.ID;
Alternatively, simply use subqueries:
SELECT (SELECT Name FROM Names WHERE id = Relations.ParentID) AS ParentName,
(SELECT Name FROM Names WHERE id = Relations.ChildID ) AS ChildName
FROM Relations;

SQLite UPDATE Value Using Foreign Key Reference

Given three tables with one table serving as a junction table which contains two foreign key columns, I'm trying to make an insert so that, given a TableA.prefix, TableA.number, TableB.prefix, and TableB.number, I can update the JunctionTable.is_archived column for the matching row in JunctionTable:
So while the matching row in JunctionTable currently looks like:
+----------------------------------------------------------------------+
| id | tblA_id | tblB_id | is_archived |
| 3 | 7 | 98 | 0 |
+----------------------------------------------------------------------+
And matching rows in TableA and TableB look like:
TableA
+----------------------------------------------+
| id | prefix | number |
| 7 | CLA | 754 |
+----------------------------------------------+
TableB
+----------------------------------------------+
| id | prefix | number |
| 98 | RED | 221 |
+----------------------------------------------+
I'd like to UPDATE the is_archived value like so:
+----------------------------------------------------------------------+
| id | tblA_id | tblB_id | is_archived |
| 3 | 7 | 98 | 1 |
+----------------------------------------------------------------------+
I've tried a few different statements based on information found here but they aren't valid:
UPDATE JunctionTable
SET is_archived = "1"
WHERE tblAid =
(SELECT id FROM TableA WHERE prefix = "CLA" AND number = 754)
AND tblB.id =
(SELECT id FROM TableB WHERE prefix = "RED" AND number = 221)
UPDATE JunctionTable
SET is_archived = "1"
WHERE (
LEFT JOIN TableA ON JunctionTable.tblA_id=TableA.id
WHERE TableA.course_prefix = "CLA" AND TableA.course_number = 754
LEFT JOIN TableB ON JunctionTable.tblB_id=TableB.id
WHERE TableB.course_prefix = "RED" AND TableB.course_number = 221)
In the first query, it looks like the problems are the names of the ID columns in your Junction table ("tblAid" and "tblB.id"), and you're using double quotes instead of single quotes. This should work:
UPDATE JunctionTable
SET is_archived = 1
WHERE tblA_id =
(SELECT id FROM TableA WHERE prefix = 'CLA' AND number = 754)
AND tblB_id =
(SELECT id FROM TableB WHERE prefix = 'RED' AND number = 221)

Suggestion needed writing a complex query - sqlite

I have 4 columns in a table called musics - 'artist','genre', 'writer' , 'producer'.
I need to write a query such that, it returns a value 0 , if there are no repetition of values corresponding to the column name; if there is a repetition of values, it should return a value 1, corresponding to that column name.
Any help is much appreciated
SELECT (COUNT(artist) <> COUNT(DISTINCT artist)) artist,
(COUNT(genre) <> COUNT(DISTINCT genre)) genre,
(COUNT(writer) <> COUNT(DISTINCT writer)) writer,
(COUNT(producer) <> COUNT(DISTINCT producer)) producer
FROM musics
Another version
SELECT
( SELECT (COUNT(*) > 0)
FROM (SELECT 1 FROM musics GROUP BY artist HAVING COUNT(*) > 1) a
) artist,
( SELECT (COUNT(*) > 0)
FROM (SELECT 1 FROM musics GROUP BY genre HAVING COUNT(*) > 1) g
) genre,
( SELECT (COUNT(*) > 0)
FROM (SELECT 1 FROM musics GROUP BY writer HAVING COUNT(*) > 1) w
) writer,
( SELECT (COUNT(*) > 0)
FROM (SELECT 1 FROM musics GROUP BY producer HAVING COUNT(*) > 1) p
) producer
Sample data
| artist | genre | writer | producer |
------------------------------------------
| artist1 | genre1 | writer1 | producer1 |
| artist2 | genre2 | writer1 | producer2 |
| artist1 | genre3 | writer3 | producer3 |
Sample output:
| artist | genre | writer | producer |
--------------------------------------
| 1 | 0 | 1 | 0 |
SQLFiddle
For Artist
select convert(bit,(count(1)-1))
from table_name
group by artist -- <-- Replace artist with column name for which duplicate
write a select count statement using distinct with specified column and another select count without distinct and compare both of them based on your requirement
you can use 4 different query with union & each query must contain count(column name) + group by clause

Sqllite query on distinct or certain value

I have an android sqllite database. It has a text column called chainid.
I'd like to return all columns from rows with DISTINCT chainids || or where chainid is equal to: "none".
So e.g.:
| ID| Name | chainid |
| 1 | widgetname1 | 12345 |
| 2 | widgetname2 | 12345 |
| 3 | widgetname3 | "none" |
| 4 | widgetname4 | 49390 |
| 5 | widgetname5 | 49390 |
Given the above table I would like my query to return 3 rows with all columns for row 2, row3 and row5. -- So DISTINCT on chainid OR where chainid = "none" with the max id selected as the distinct row
Can I achieve this in one query?
I could return all and then process afterwards in java, but this is inefficient.
What about
select *
from table where id in
( select max(id)
from table
group by chainid
where chainid != 'none'
union
select id
from table
where chainid = 'none'
)

Resources