I have a very complex query going on in SQLite, and I need a bit of help understanding how to do it.
The following example is of my Database:
Category:
CatID | CatTitle
----------------
1 | XYZ
2 | Sample
Content:
ItemID | ItemCatID | ItemText | ItemText2 | ItemText3 | ItemText4
-----------------------------------------------------------------
1 | 1 | Test | Bla | Sample | MoreContent
2 | 1 | Test2 | BlaBla | Sample2 | Other Content
3 | 2 | Test3 | BlaBla2 | Sample3 | Other Content2
Now, I basically want to do a query, on a search string.. (i.e. "%XYZ%" with the wildcards) and I want to search not only the CatTitle, but also ItemText, ItemText2 and ItemText3
The parameters I want to return though are: CatID, CatTitle, ItemID, and if possible, "ItemFilteredText" (which can be anything from ItemText to ItemText4, depending on which is the match)
Heres the thing, If the Query Matches CatTitle, then if it returns ItemID, it should be the FIRST ItemID and NOT the LAST ItemID
I have the following SQL somewhat working...
select DISTINCT Category.CatID,
Category.CatTitle,
Content.ItemID,
Content.ItemText,
Content.ItemText2,
Content.ItemText3
from Content,Category
where Category.CatID = Content.ItemCatID
AND ( Category.CatTitle like'%XYZ%'
OR Content.ItemText like '%XYZ%'
OR Content.ItemText2 like '%XYZ%'
OR Content.ItemText3 like '%XYZ%')
GROUP BY Category.CatTitle ORDER BY Category.CatID ASC
It returns the data... but Grouping By Category.CatTitle means that Content.ItemID would return 2, instead of 1
Any Ideas?
Assuming that you are using integers for content.ItemID and the first result is characterized by a lower ItemID modify the query to include min(Content.ItemID)
select DISTINCT Category.CatID, Category.CatTitle, min(Content.ItemID), Content.ItemText, Content.ItemText2, Content.ItemText3 from Content,Category where Category.CatID = Content.ItemCatID AND (Category.CatTitle like'%XYZ%' OR Content.ItemText like '%XYZ%' OR Content.ItemText2 like '%XYZ%' OR Content.ItemText3 like '%XYZ%') GROUP BY Category.CatTitle ORDER BY Category.CatID ASC
should do the work.
Related
I am trying to return one json per unique value in a column.
However, when I try to select from a sub-query the entire result set is returned.
Example Table
| json | column |
|--------|--------|
| {obj1} | 1 |
| {obj2} | 1 |
| {obj3} | 2 |
Example Query
select distinct
[json]
from someTable
where [column] in (
select distinct
[column]
from someTable
)
Actual Output
| json |
|--------|
| {obj1} |
| {obj2} |
| {obj3} |
Expected Output
| json |
|--------|
| {obj1} |
| {obj3} |
How can I select just 1 json per unique column value?
If doesn't Matter output Related To Column is obj1 Or obj2 you must Use Group By Like this :
SELECT
Min(JSon) AS Json ,Column
FROM
someTable
Group By column
If you want the 1st [json] of each column then use row_number():
select t.[json] from (
select
[json],
row_number() over (partition by column order by id) rn
from someTable
) t
where t.rn = 1
I have an Images, Orders and OrderItems table, I want to match for any images, if any has already been bought by the User passed as parameters by displaying true or false in an IsBought column.
Select Images.Id,
Images.Title,
Images.Description,
Images.Location,
Images.PriceIT,
Images.PostedAt,
CASE WHEN OrderItems.ImageId = Images.Id THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT) END
AS 'IsBought'
FROM Images
INNER JOIN Users as u on Images.UserId = u.Id
LEFT JOIN Orders on Orders.UserId = #userId
LEFT JOIN OrderItems on Orders.Id = OrderItems.OrderId and OrderItems.ImageId = Images.Id
Group By Images.Id,
Images.Title,
Images.Description,
Images.Location,
Images.PriceIT,
Images.PostedAt,
OrderItems.ImageId,
Orders.UserId
When I use this CASE WHEN I have duplicates when the item has been bought where IsBought is True and the duplicate is False.
In the case where the Item has never been bought, there is no duplicates, IsBought is just equal to False
----------------------------------
| User | type |
----------------------------------
| Id | nvarchar(450) |
----------------------------------
| .......|
----------------------------------
----------------------------------
| Orders | type |
----------------------------------
| Id | nvarchar(255) |
----------------------------------
| UserId | nvarchar(450) |
----------------------------------
| ........................... |
----------------------------------
----------------------------------
| OrderItems | type |
----------------------------------
| Id | nvarchar(255) |
----------------------------------
| OrderId | nvarchar(255) |
----------------------------------
| ImageId | int |
----------------------------------
----------------------------------
| Images | type |
----------------------------------
| Id | int |
----------------------------------
| UserId | nvarchar(450) |
----------------------------------
| Title | nvarchar(MAX) |
----------------------------------
| Description| nvarhar(MAX) |
----------------------------------
| ......................... |
----------------------------------
Any ideas on how I could just have one row per Images with IsBought set to true or false but not duplicates?
I would like something like this:
----------------------------------------------------------------------------
| Id | Title | Description | Location | PriceIT | Location | IsBought |
----------------------------------------------------------------------------
| 1 | Eiffel Tower | .... | ...... | 20.0 | Paris | true |
----------------------------------------------------------------------------
| 2 | Tore di Pisa | .... | ...... | 20.0 | Italia | false |
---------------------------------------------------------------------------
| etc ......
---------------------------------------------------------------------------
Your query logic looks suspicious. It is unusual to see a join that consists only of a comparison of a column from the unpreserved table to a parameter. I suspect that you don't need a join to users at all since you seem to be focused on things "bought" by a person and not things "created" (which is implied by the name "author") by that same person. And a group by clause with no aggregate is often a cover-up for a logically flawed query.
So start over. You want to see all images apparently. For each, you simply want to know if that image is associated with any order of a given person.
select img.*, -- you would, or course, only select the columns needed
(select count(*) from Sales.SalesOrderDetail as orddet
where orddet.ProductID = img.ProductID) as [Order Count],
(select count(*) from Sales.SalesOrderDetail as orddet
inner join Sales.SalesOrderHeader as ord
on orddet.SalesOrderID = ord.SalesOrderID
where orddet.ProductID = img.ProductID
and ord.CustomerID = 29620
) as [User Order Count],
case when exists(select * from Sales.SalesOrderDetail as orddet
inner join Sales.SalesOrderHeader as ord
on orddet.SalesOrderID = ord.SalesOrderID
where orddet.ProductID = img.ProductID
and ord.CustomerID = 29620) then 1 else 0 end as [Has Ordered]
from Production.ProductProductPhoto as img
where img.ProductID between 770 and 779
order by <something useful>;
Notice the aliases - it is much easier to read a long query when you use aliases that are shorter but still understandable (i.e., not single letters). I've included 3 different subqueries to help you understand correlation and how you can build your logic to achieve your goal and help debug any issues you find.
This is based on AdventureWorks sample database - which you should install and use as a learning tool (and to help facilitate discussions with others using a common data source). Note that I simply picked a random customer ID value - you would use your parameter. I filtered the query to a range of images to simplify debugging. Those are very simple but effective methods to help write and debug sql.
I know it is posible to serach multiple columns with one value.
I would like to serach 3-4 columns for 4 maybe 5 values
I want to check if any of my choosen columns have a certain value in them.
Example
Column 1 | Column 2 | Column 3 | Column 4
| | |
Hello | | | = True
| | |
| Goodbye | | = True
| | Hello | Goodbye = True
| | |
| Hello | | = True
| | |
| | Goodbye | = True
In the example I would like SQL to pull the data from all of the lines that have Hello or Goodbye even both in some cases.
Is there a way to do what I want?
There is one more way...
SELECT *
FROM TableName
WHERE 'Value1' IN (Col1,Col2,Col3...) OR 'Val2' in (Col1,Col2,Col3...) OR ...
If it's only 3 or 4 columns, the simplest solution would be something like this:
SELECT *
FROM TableName
WHERE Column1 IN('Hello', 'Goodbye')
OR Column2 IN('Hello', 'Goodbye')
OR Column3 IN('Hello', 'Goodbye')
OR Column4 IN('Hello', 'Goodbye')
Forgot to follow with my solution: I needed to join 2 tables and search across the columns. They ****ed up and made the id of t1 a varchar, smh, and some of them had nulls so we needed to check for them lest our results were ****ed (this is why the selected answer wouldn't work for me). You don't need the aliases but if you were going deeper it helps keep things straight.
Use "+" operator to add columns to a WHERE, check for nulls, and caste if you need too.
SELECT *
FROM Table1 AS t1
LEFT OUTER JOIN Table2 AS t2
ON t1.id = t2.id
WHERE( ISNULL(CONVERT(VARCHAR,t1.id),'') + ISNULL(t1.name,'') + ISNULL(t1.desc,'') + ISNULL(t2.company,'')) LIKE '%xbox%'
I know there are several unpivot / cross apply discussions here but I was not able to find any discussion that covers my problem. What I've got so far is the following:
SELECT Perc, Salary
FROM (
SELECT jobid, Salary_10 AS Perc10, Salary_25 AS Perc25, [Salary_Median] AS Median
FROM vCalculatedView
WHERE JobID = '1'
GROUP BY JobID, SourceID, Salary_10, Salary_25, [Salary_Median]
) a
UNPIVOT (
Salary FOR Perc IN (Perc10, Perc25, Median)
) AS calc1
Now, what I would like is to add several other columns, eg. one named Bonus which I also want to put in Perc10, Perc25 and Median Rows.
As an alternative, I also made a query with cross apply, but here, it seems as if you can not "force" sort the rows like you can with unpivot. In other words, I can not have a custom sort, but only a sort that is according to a number within the table, if I am correct? At least, here I do get the result like I wish to have, but the rows are in a wrong order and I do not have the rows names like Perc10 etc. which would be nice.
SELECT crossapplied.Salary,
crossapplied.Bonus
FROM vCalculatedView v
CROSS APPLY (
VALUES
(Salary_10, Bonus_10)
, (Salary_25, Bonus_25)
, (Salary_Median, Bonus_Median)
) crossapplied (Salary, Bonus)
WHERE JobID = '1'
GROUP BY crossapplied.Salary,
crossapplied.Bonus
Perc stands for Percentile here.
Output is intended to be something like this:
+--------------+---------+-------+
| Calculation | Salary | Bonus |
+--------------+---------+-------+
| Perc10 | 25 | 5 |
| Perc25 | 35 | 10 |
| Median | 27 | 8 |
+--------------+---------+-------+
Do I miss something or did I something wrong? I'm using MSSQL 2014, output is going into SSRS. Thanks a lot for any hint in advance!
Edit for clarification: The Unpivot-Method gives the following output:
+--------------+---------+
| Calculation | Salary |
+--------------+---------+
| Perc10 | 25 |
| Perc25 | 35 |
| Median | 27 |
+--------------+---------+
so it lacks the column "Bonus" here.
The Cross-Apply-Method gives the following output:
+---------+-------+
| Salary | Bonus |
+---------+-------+
| 35 | 10 |
| 25 | 5 |
| 27 | 8 |
+---------+-------+
So if you compare it to the intended output, you'll notice that the column "Calculation" is missing and the row sorting is wrong (note that the line 25 | 5 is in the second row instead of the first).
Edit 2: View's definition and sample data:
The view basically just adds computed columns of the table. In the table, I've got Columns like Salary and Bonus for each JobID. The View then just computes the percentiles like this:
Select
Percentile_Cont(0.1)
within group (order by Salary)
over (partition by jobID) as Salary_10,
Percentile_Cont(0.25)
within group (order by Salary)
over (partition by jobID) as Salary_25
from Tabelle
So the output is like:
+----+-------+---------+-----------+-----------+
| ID | JobID | Salary | Salary_10 | Salary_25 |
+----+-------+---------+-----------+-----------+
| 1 | 1 | 100 | 60 | 70 |
| 2 | 1 | 100 | 60 | 70 |
| 3 | 2 | 150 | 88 | 130 |
| 4 | 3 | 70 | 40 | 55 |
+----+-------+---------+-----------+-----------+
In the end, the view will be parameterized in a stored procedure.
Might this be your approach?
After your edits I understand, that your solution with CROSS APPLY would comes back with the right data, but not in the correct output. You can add constant values to your VALUES and do the sorting in a wrapper SELECT:
SELECT wrapped.Calculation,
wrapped.Salary,
wrapped.Bonus
FROM
(
SELECT crossapplied.*
FROM vCalculatedView v
CROSS APPLY (
VALUES
(1,'Perc10',Salary_10, Bonus_10)
, (2,'Perc25',Salary_25, Bonus_25)
, (3,'Median',Salary_Median, Bonus_Median)
) crossapplied (SortOrder,Calculation,Salary, Bonus)
WHERE JobID = '1'
GROUP BY crossapplied.SortOrder,
crossapplied.Calculation,
crossapplied.Salary,
crossapplied.Bonus
) AS wrapped
ORDER BY wrapped.SortOrder
Hi i've got this little issue while sorting items within our database.
table data is like this:
id | description | parent | rowlevel
100 | item 12222 | -none- | 0
SET | item 12345 | -none- | 0
201 | item 22345 | -SET - | 1
I'd like have to output sorted on "id" though also have it sorted on a way that the "childen" come after the "parents".
I know this would be easier with a different table layout though changing that is not an option.
planned result would be:
id | description | parent | rowlevel
100 | item 12222 | -none- | 0
SET | item 12345 | -none- | 0
201 | item 22345 | -SET - | 1
301 | item 22345 | -SET - | 1
401 | item 22345 | -SET - | 1
ST2 | item 12345 | -none- | 0
211 | item 22345 | -ST2 - | 1
321 | item 22345 | -ST2 - | 1
101 | item 22345 | -ST2 - | 1
i've tried using order by but though its result has the rowlevel 1 items together the item's parent results at the bottom. together with the other parents.
I am not experiences using joins and have no clue if its posible to have a join on the table itself which will resolve this.
the only think I can think of is some sort of nested SQL query.
but besides that I am not sure if that will work. I am also concerned this will eat resources and have a great impact on the performance.
As long es you have only 1 level, just add the following order criterion to your SQL:
ORDER BY COALESCE(parent, id), rowlevel
(Assuming that -none- is actually null and SET/-SET - is actually some kind of numeric id.)
If you have more than 1 level of nesting, you will require some kind of recursive CTE.
You can use a recursive CTE:
WITH CTE AS
(
SELECT t1.[id], t1.[description], t1.[parent],
[rowlevel] = 0
FROM dbo.Table1 t1
WHERE t1.parent = '-none-'
UNION ALL
SELECT t2.[id], t2.[description], t2.[parent],
[rowlevel] = CTE.[rowlevel] + 1
FROM dbo.Table1 t2 INNER JOIN CTE
ON t2.parent = CTE.id
)
SELECT * FROM CTE
ORDER BY rowlevel, id
DEMO