Return text next to search term based on phrase in select - sql

I have a query I'm trying to put together where I have a search phrases in the database that we use to query our fulltext index. Currently the below query is working.
select top 100 p.ID, dtp.Phrase,
from table1 p
left join table2 d on d.PropertyId = p.PropertyId
left join table3 dt on dt.DocumentId = d.DocumentId
left join table4 dtm on dtm.DocumentTextId = dt.DocumentTextId
left join table 5 dtp on dtm.DocumentTypePhraseId = dtp.DocumentTypePhraseId
However I also want to include a portion of the searched text after dtp.Phrase. I was considering doing a subquery in the select statement.
select top 100 p.ID, dtp.Phrase,
(
select sdt.DocText
from mytable sdt
where sdt.Doctextid = dt.doctextid ) as DocText
from table1 p
left join table2 d on d.PropertyId = p.PropertyId
left join table3 dt on dt.DocumentId = d.DocumentId
left join table4 dtm on dtm.DocumentTextId = dt.DocumentTextId
left join table5 dtp on dtm.DocumentTypePhraseId = dtp.DocumentTypePhraseId
where p.ID in ('1053468')
The DocText I want returned. Here's an example.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec ullamcorper tellus. Integer ac dui enim. Morbi lorem lorem, convallis a dolor ac, facilisis malesuada est. Sed mauris massa, consequat et pulvinar vitae, hendrerit sed ligula. Nam ornare blandit nisi sed euismod. Nunc dictum neque vitae mi sagittis, quis convallis ante maximus. Nullam a erat vitae dolor porttitor feugiat vel vel nisl. Quisque turpis sapien, ullamcorper a malesuada in, pellentesque faucibus nulla. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aenean diam est, tincidunt in ultrices vel, venenatis ut dolor.
In the paragraph above let's say I want to search for the word maximus. But I don't want to return the entire paragraph. I just want to return the following
quis convallis ante maximus. Nullam a erat vitae
Any help is appreciated.

Related

Would filtering by order ID from nvarchar(MAX) column benefit from fulltext search?

In my table I have a nvarchar(MAX) column which holds data about our orders in XML form. Another department often has to get information from the table by, most commonly, looking for a certain order ID in that column but we all need to be able to look for any part of the text in the column.
The problem is that the order IDs and other filter/search criteria are unique to each order and are not words I can define in stopwords or stoplists and new ones are generated for new orders, ofc.
Since the table is growing in size queries with a LIKE clause take a really long time, yet I cannot think how my colleagues can get information about an order except by looking for things like its order ID, a part serial number or a piece of text. We have no control over the XML order data, furthermore it doesn't have a standardised structure, which is to say every order type has its own XML structure and there are too many to separate into different tables and we can't extract separate elements into different columns as we don't have control over the processing, only over the storage of the data.
Since an index would be futile in this case I started reading about fulltext search, but would that help because of the reasons I mentioned and if not is there a better alternative?
EDIT:
Adding example messages being stored in the nvarchar(MAX) column (there are approx. 23 other types not shown here, for the moment):
<?xml version='1.0' encoding='UTF-8'?>
<ServiceRequest>
<OrderID>GT123456789123465</OrderID>
<CreatedBy>some.person</CreatedBy>
<CreationTime>2021-08-18</CreationTime>
<CustomerReference>INC123456</CustomerReference>
<CustomerContract>123456</CustomerContract>
<ShortDescription>A little bit of text</ShortDescription>
<StockLocation>Text-Identifier</StockLocation>
<DueDate>2021-08-19</DueDate>
<ExpectedDeliveryDate>2021-08-19T10:30:00</ExpectedDeliveryDate>
<ServiceLevel>Same-Day</ServiceLevel>
<DeliveryLocation>SITE</DeliveryLocation>
<Site>Address of a building or something</Site>
<ContactName>Name of a person</ContactName>
<ContactPhone>0123456789</ContactPhone>
<DocTypeID>123</DocTypeID>
<DeliveryAddress>
<Address1>Address1</Address1>
<Address2>More details about address</Address2>
<City>Some city</City>
<Postcode>LOL KEK</Postcode>
<Country>Narnia</Country>
</DeliveryAddress>
<Parts>
<Part>
<UniqueID>168468468</UniqueID>
<PartNumber>#ABCDE-1234-ABCDE</PartNumber>
<Description>Example TV set with model name</Description>
<Quantity>1</Quantity>
<Returnable>Y</Returnable>
<ReturnInformation>TBC</ReturnInformation>
<LinkedDemandId>123456789</LinkedDemandId>
</Part>
</Parts>
</ServiceRequest>
.
<?xml version='1.0' encoding='UTF-8'?>
<Engineer>
<PersonId>some.guy</PersonId>
<SearchName>Some Guy</SearchName>
<personemail>some.guy#company.com</PersonEmail>
<PersonPhone>00000000000</PersonPhone>
<Address>
<Zip>LOL KEK</Zip>
<CountryId>US</CountryId>
</Address>
</Engineer>
.
<WarehouseUpdate>
<WarehouseId>Warehouse-name-123456</WarehouseId>
<WarehouseDescription>Friendlier WH name</WarehouseDescription>
<CurrencyId>USD</CurrencyId>
<CostDomainId>MAIN</CostDomainId>
<NodeId>SSL</NodeId>
<SupplySource>W</SupplySource>
<ReturnWarehouse>Warehouse-ID</ReturnWarehouse>
<IsAutoReceive>Y</IsAutoReceive>
<IsRepairWhse>N</IsRepairWhse>
<IsReplenishable>Y</IsReplenishable>
<SupplyWarehouse>Warehouse-ID</SupplyWarehouse>
<WarehouseTypeId>ABC</WarehouseTypeId>
<Address>
<Zip>LOL KEK</Zip>
<CountryId>US</CountryId>
</Address>
</WarehouseUpdate>
.
<briefing>
<incident>
<serviceProvider>A long name of a company that provides a service</serviceProvider>
<receiverURL>https://www.google.com/some/url/that/is/used</receiverURL>
<incidentNumber>123456789</incidentNumber>
<taskNumber>123456789</taskNumber>
<taskAssignmentID>123456789</taskAssignmentID>
<taskCreationDate>2021-02-31</taskCreationDate>
<taskCreationTime>10:32:13</taskCreationTime>
<sendDate>2021-02-31</sendDate>
<sendTime>10:32:27</sendTime>
<request>ABC</request>
<urgency>ABC</urgency>
<severity>D</severity>
<customerName>Name of a company</customerName>
<helpdeskNumber>123456789</helpdeskNumber>
<originalCustomerReference>123456789</originalCustomerReference>
<projectNumber/>
<project/>
<callerFirstName>Some</callerFirstName>
<callerLastName>Person</callerLastName>
<callerPhone>123456789123456789</callerPhone>
<callerPhoneType>ABC</callerPhoneType>
<callerEmailaddress/>
<callerPreferredLanguage/>
<communicationPreference/>
<installedAtAddress1>Address short</installedAtAddress1>
<installedAtAddress2/>
<installedAtAddress3>More address details</installedAtAddress3>
<installedAtAddress4>Even more address details</installedAtAddress4>
<installedAtCity>Washington</installedAtCity>
<installedAtState/>
<installedAtProvince/>
<installedAtPostalCode>LOL KEK</installedAtPostalCode>
<installedAtCountry>US</installedAtCountry>
<installedAtPhone/>
<installedAtFax/>
<installedAtEmail/>
<productSerialNumber>ABCDF123456789</productSerialNumber>
<productTag>ABCDF123456789</productTag>
<productSystem>123456</productSystem>
<productItemNumber>123456789123456789</productItemNumber>
<productItemDescription>This is a thingy</productItemDescription>
<productComponentNumber/>
<productComponentDescription/>
<productServiceGroupNumber>12</productServiceGroupNumber>
<customerSerialNumber/>
<defectDescription>ABCD::ABCD::ABCD EF::ABCD EF</defectDescription>
<orderDescription>Lorem ipsum</orderDescription>
<taskType>In summet idit</taskType>
<customerErrorCode/>
<problemCode>corpsem mepsem dopsem</problemCode>
<resolutionSummary/>
<resolutionCode/>
<reporteddate>2021-05-12</reporteddate>
<reportedtime>10:30:44</reportedtime>
<customerTimezone>EET</customerTimezone>
<coverage>-ABC-EF-</coverage>
<contractServiceNumber>123456789123456789</contractServiceNumber>
<plannedStartDate>2021-05-12</plannedStartDate>
<plannedStartTime>10:32:13</plannedStartTime>
<plannedEndDate>2021-05-14</plannedEndDate>
<plannedEndTime>10:32:44</plannedEndTime>
<chargeableFlag/>
<vkOrg>12AB</vkOrg>
<attribute1/>
<attribute2/>
<attribute3>AB</attribute3>
<attribute4/>
<attribute5/>
<attribute6/>
<attribute7/>
<attribute8/>
<attribute9/>
</incident>
<incidentNotes>
<technicianNote>Went to lunch, bought a snack</technicianNote>
<technicianNote>AB 11.11 11/11/2021
A huge block of text incoming
Here a monumental, monolithic, megalithic block of text resides that has numerous details written in freeform however the person doing the thing decides
There is some structure to the text but it is completely specific to this one type of XML message.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eu feugiat enim. Praesent malesuada, diam ut ornare tristique, ipsum dolor rutrum enim, et sodales lectus mi at ex. Nulla in varius nisl. Nunc non enim augue. Integer condimentum tempor lacus, non maximus tortor dictum a. Donec dapibus urna nulla, ac tempus justo sodales sed. Cras lacinia tempus lacinia. Sed fermentum libero vel lectus ornare, at egestas eros dignissim. Quisque ac vehicula erat. Morbi id ultrices sem, auctor dapibus ligula. Vivamus vestibulum consectetur ligula non viverra. Proin id mi non ipsum consectetur interdum. Aenean id posuere metus.
Aenean diam justo, ultrices sed cursus eget, posuere eget justo. Maecenas egestas mi et rutrum auctor. Fusce tincidunt ac purus ut gravida. Proin ac condimentum nibh, id venenatis nibh. Sed eu turpis non sem venenatis posuere eu sit amet leo. Vivamus velit lacus, tempor quis dolor vel, sagittis vulputate risus. Praesent dignissim sed turpis vel porta. Duis elit ante, pellentesque sit amet nisl eu, ullamcorper varius ex. Aenean tortor ligula, posuere sed tempor eget, consequat ut orci. Vestibulum eu aliquet ante. Ut eros ex, dignissim nec accumsan eu, posuere nec ligula. Cras tempor volutpat tempor. Duis vitae dui sit amet diam porttitor viverra. Aliquam ornare, turpis ut pulvinar bibendum, urna eros sodales turpis, sed malesuada felis massa in neque. Etiam venenatis volutpat diam eget placerat. Integer ultrices vulputate neque ut ullamcorper.
</technicianNote>
</incidentNotes>
<ibaseNotes>
<serialnumberNote/>
</ibaseNotes>
</briefing>
Also I think I deceived you by accident, most commonly order IDs are being searched but we need to be able to search/filter by any part of the XML message, for example I need to be able to find all messages that contain "some.person" in them. I'll go back and edit that.
Ideally you should store XML in an xml column. Then you can use XQuery to search. An XML index on the column may be wise.
But you can also cast the data to XML (at a cost of lower eficiency), like this
CROSS APPLY (VALUES (
CAST(CAST(yourData AS varchar(max)) AS xml)
) ) v(xmlData)
Cast to varchar is necessary because the XML is defined with UTF-8.
Then you can use XQuery, like this for example
WHERE v.xmlValue.exist('/Engineer/PersonId[contains(text()[1], "some.guy")]') = 1
or v.xmlValue.exist('/Engineer/PersonEmail[contains(text()[1], "some.guy")] ') = 1
Or pass through a SQL variable
WHERE v.xmlValue.exist('/Engineer/PersonId[contains(text()[1], sql:variable("#toSearch"))]') = 1
or v.xmlValue.exist('/Engineer/PersonEmail[contains(text()[1], sql:variable("#toSearch"))] ') = 1
SQL Fiddle
To find text in any node, you can use //*, which means "descend any depth, matching any node name"
WHERE v.xmlValue.exist('//*[contains(text()[1], sql:variable("#toSearch"))]') = 1
That can be inefficient though.

Annotate Data in between Markup

I'm trying to write a rule to detect Data in between Markup tags.
Input data format is fixed for example
<1> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim</1>
<2> nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim</2>
What i basically need here to detect data in between start and end tag
in my case output should be 1 and 2
I'm trying below rule.
Document{->ADDRETAINTYPE(MARKUP)};
STRING sStart = "<";
STRING sEnd = ">";
DECLARE spanStart;
DECLARE spanEnd;
DECLARE ZONE;
sStart -> spanStart;
sEnd -> spanEnd;
spanStart NUM spanEnd{->MARK(ZONE,2)};
But value is not getting detected as 1 & 2 are not detected as number
"1" and "2" are not detected as NUM because they are MARKUP. The seeding creates a disjunct non-overlapping partitioning of the document. If you want to create an annotation within a currently smallest part, e.g., in your use case MARKUP, you can do that with a simple regex rule as you did in your question with spanStart and spanEnd.
I would use something like:
MARKUP->{"\\d+"-> ZONE;};
or
MARKUP->{"</?(\\d+)>"-> 1 = ZONE;};
DISCLAIMER: I am a developer of UIMA Ruta

Insert string randomly into another string

Does anyone have a good method for inserting all items from a list randomly into another string? For example if I have paragraph of text and I want to insert urls randomly after sentences. The Urls are stored in a list object. How would I go about doing this? I was thinking I could count the number of periods and other punctuation, but I would somehow have to store the location of each period as well. If anyone could point me in the right direction i would appreciate it.
I think the logic is as follows:
count periods,
store period indexes in list,
get random index from list,
insert text after that index by adding 1 to the index
Does this work for you?
var rnd = new Random();
var urls = new [] { "www.a.com", "www.b.com" };
var text = "I like apples. I like bananas.";
var query =
from t in text.Split(new [] { '.' }, StringSplitOptions.RemoveEmptyEntries)
from x in new [] { t, ". ", urls[rnd.Next(urls.Length)] }
select x;
var result = String.Join("", query);
I like apples. www.b.com I like bananas. www.a.com
Here you go.
Module Module1
' String to insert into
Const target As String = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse vel posuere neque, quis suscipit diam. Proin congue dapibus elit, ut tempus leo. Suspendisse suscipit mi quis purus laoreet facilisis. Sed eget arcu eu risus sodales posuere. Nulla ut nulla urna. Quisque eu eleifend metus. Mauris suscipit rhoncus eros at ultrices. Cras sodales facilisis mauris, vitae condimentum mi tempus a. Suspendisse hendrerit, arcu sit amet viverra placerat, eros quam venenatis enim, id tincidunt felis mauris id augue. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur ac ullamcorper sem, sed porta orci. Praesent euismod, ipsum et sagittis gravida, purus ipsum venenatis ipsum, quis congue risus erat in magna. Donec nec elit ut velit faucibus efficitur. Donec facilisis, tellus et volutpat hendrerit, dui sem pulvinar lectus, sit amet fringilla sem mi eget elit."
' Urls to insert
Private injections As String() = New String() {"http://lorempixel.com/output/cats-q-c-640-480-1.jpg", "http://lorempixel.com/output/cats-q-c-640-480-2.jpg", "http://lorempixel.com/output/cats-q-c-640-480-3.jpg", "http://lorempixel.com/output/cats-q-c-640-480-4.jpg"}
Sub Main()
Dim sentence As New System.Text.RegularExpressions.Regex("[^.!?]+[.!?]")
Dim result As New System.Text.StringBuilder()
Dim n As Integer = injections.Count()
' Break sentence at punctuation.
For Each m As System.Text.RegularExpressions.Match In sentence.Matches(target)
' Get index of one of our injection strings at random.
Dim i As Integer = CInt(Math.Ceiling(Rnd() * n)) - 1
result.Append(m).Append(injections(i))
Next
Console.WriteLine(result.ToString())
Console.ReadKey()
End Sub
End Module

How to set same "STRING" as start and end reference to copy the message within those references?

I have an email that has a long body. I want to send part of the email body by setting a starting "STRING" reference and an ending same "STRING" reference.
Let's say the "STRING" = "Good day!"
Whenever the macro set the first string "Good day!" in the email body, I want the next "Good day!" string to be the ending reference without searching/finding another "Good day!" string so that the message within those two references can be copied to be sent as a new mail.
I found this code that uses a UNIQUE string but I need the next string occurrence only after the first string reference.
http://www.outlookcode.com/codedetail.aspx?id=985
With this on hand, I'm thinking just to replace the 2nd "Good day!" with a UNIQUE string so that I can use this code but I still don't know how to search/find for the 2nd occurrence of the same string.
Consider the following approximation of an email's 'body text'
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque fringilla mi et aliquam ornare. Sed et dolor posuere, feugiat mi ac, mattis augue. Good day! Ut lorem sem, pulvinar a erat a, tempus congue lorem. Nulla semper cursus ante ac euismod. Sed rutrum odio a nulla consectetur, scelerisque lacinia risus consectetur. Good day! Fusce sit amet vulputate lorem, eu aliquam diam.
Pass that text as a string through this function.
Function partial_body(sBDY As String, Optional sFND As String = "Good day!", Optional bINCL As Boolean = False)
Dim s As Long, f As Long
s = InStr(1, sBDY, sFND, vbTextCompare) - ((Not bINCL) * Len(sFND))
f = InStr(s + 1, sBDY, sFND, vbTextCompare) + (bINCL * Len(sFND))
partial_body = Trim(Mid(sBDY, s, f - s - (bINCL * Len(sFND)) * 2))
End Function
Result for partial_body(<body>)
Ut lorem sem, pulvinar a erat a, tempus congue lorem. Nulla semper cursus ante ac euismod. Sed rutrum odio a nulla consectetur, scelerisque lacinia risus consectetur.
Result for partial_body(<body>, "Good day!", True)
Good day! Ut lorem sem, pulvinar a erat a, tempus congue lorem. Nulla semper cursus ante ac euismod. Sed rutrum odio a nulla consectetur, scelerisque lacinia risus consectetur. Good day!

Get all information for products by categories - SQL?

Since this is the best page I've ever found in case of question like this, I wanna ask this here. I'm a little bit confused here. I'm a beginner in SQL statements, so I need your help, please. I have three tables:
product
product_category
product_to_category
I show you the exported SQL file, so you may get this:
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS */;
/*!40101 SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
CREATE TABLE IF NOT EXISTS `product` (
`productID` int(6) NOT NULL AUTO_INCREMENT,
`productTitle` varchar(255) NOT NULL,
`productDescription` text NOT NULL,
`productPrice` double NOT NULL DEFAULT '0',
`productQuantity` int(5) NOT NULL,
PRIMARY KEY (`productID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `product` (`productID`, `productTitle`, `productDescription`, `productPrice`, `productQuantity`) VALUES
(1, 'Chlor 5L', 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. \r\n\r\nDuis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. \r\n\r\nUt wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. \r\n\r\nNam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. \r\n\r\nDuis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. ', 14.95, 50),
(2, 'Chlor 15L', 'Mit diesem Kanister kommen Sie etwa 27.000 Liter aus.', 50, 13),
(3, 'Chlor 20L', 'Mit diesem Kanister kommen Sie etwa 37.000 Liter aus.', 60, 2),
(4, 'Chlor 25L', 'Mit diesem Kanister kommen Sie etwa 47.000 Liter aus.', 79, 11),
(5, 'Kieselgur 50kg', 'Eine menge Kieselgur zum säubern.', 69.99, 9);
CREATE TABLE IF NOT EXISTS `product_category` (
`categoryID` int(3) NOT NULL AUTO_INCREMENT,
`categoryName` varchar(255) NOT NULL,
`categoryDescription` text NOT NULL,
PRIMARY KEY (`categoryID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `product_category` (`categoryID`, `categoryName`, `categoryDescription`) VALUES
(1, 'Schwimmbecken', 'Hier finden Sie alle Produkte rund um das Thema Schwimmbecken.'),
(2, 'Whirlpool', 'Hier finden Sie alle Produkte rund um das Thema Whirlpools.'),
(3, 'Sauna', 'Hier finden Sie alle Produkte rund um das Thema Sauna.'),
(4, 'Infrarot', 'Hier finden Sie alle Produkte rund um das Thema Infrarotkabinen.');
CREATE TABLE IF NOT EXISTS `product_to_category` (
`categoryID` int(3) NOT NULL,
`productID` int(6) NOT NULL,
`productAddedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`categoryID`,`productID`),
KEY `productID` (`productID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `product_to_category` (`categoryID`, `productID`, `productAddedTime`) VALUES
(1, 1, '2011-11-27 13:57:12'),
(1, 2, '2011-11-27 13:57:12'),
(1, 3, '2011-11-27 13:57:12'),
(1, 4, '2011-11-27 13:57:12'),
(1, 4, '2011-11-27 13:57:12'),
(2, 1, '2011-11-27 13:57:12');
ALTER TABLE `product_to_category`
ADD CONSTRAINT `product_to_category_ibfk_2` FOREIGN KEY (`categoryID`) REFERENCES `product_category` (`categoryID`),
ADD CONSTRAINT `product_to_category_ibfk_3` FOREIGN KEY (`productID`) REFERENCES `product` (`productID`);
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=#OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=#OLD_COLLATION_CONNECTION */;
So, what I wanna do is: I want to get all information of ALL products. I want to group them on ONE page by there categories. In addition I wanna show the number of products in each category. I do not know, how to do this. I get the right number of products per category with this statement, but just on product. But I want alle information on products of ALL products in ALL categories, hopefully I stated my point, otherwise you may ask again. I try to explain it.
SELECT COUNT(ptc.productID) AS productCount, pc.categoryName, p.productTitle, p.productPrice
FROM product_category pc
JOIN product_to_category ptc ON pc.categoryID = ptc.categoryID
JOIN product p ON ptc.productID = p.productID
GROUP BY pc.categoryName
I hope you have an answer for me...
Want I wanna do is a overview like this:
Schwimmbecken (5 products)
- Chlor 5L (14.95)
- Chlor 15L (50.00)
- Chlor....
Whirlpool (1 product)
- Chlor 5L (14.95)
Hope this was enough to show ya...
I think you are close but I would 'start' with either product or category.
I would start with product, link to product_category and then to catergory e.g. something like:
SELECT COUNT(p.productID) AS productCount, c.categoryName, p.productTitle, p.productPrice
FROM product p
JOIN product_to_category ptc ON ptc.categoryID = p.productID
JOIN category c ON ptc.catgeory_id = c.categoryID
ORDER BY c.categoryName
Start with this, examine the results and then add grouping as appropriate.
use (corrected version)
SELECT DISTINCT
c.categoryName || '(' || c.cnt || ' products)' title,
x.productTitle || '(' || x.productPrice || ')' productinfo
FROM
(
select
pc.categoryid,
pc.categoryName,
count(distinct p2c.productID) cnt
from product_category pc
INNER JOIN product_to_category p2c ON p2c.categoryid = pc.categoryid
group by pc.categoryid, pc.categoryName
) c
INNER JOIN
(
SELECT DISTINCT
ptc.categoryid,
p.productTitle,
p.productPrice
FROM product p
INNER JOIN product_to_category ptc ON p.productID = ptc.productID
) x ON x.categoryid = c.categoryid
ORDER BY 1, 2
This will give what you ask for except for one thing - the title will be repeated as often as there are products in the respective category... that part can't be handled via SQL itself, you will have to handle it in your code...
EDIT - as per comments:
The above select makes inner join between two SELECTs... first gets one row per category plus the count of products in that category... second gets all products per category... these are joined via the categoryid...
Just tried it with your sample data and got the following result:
TITLE PRODUCTINFO
Schwimmbecken(4 products) Chlor 15L(50)
Schwimmbecken(4 products) Chlor 20L(60)
Schwimmbecken(4 products) Chlor 25L(79)
Schwimmbecken(4 products) Chlor 5L(14,95)
Whirlpool(1 products) Chlor 5L(14,95)
BTW: your sample data seems off... you have two times productId 4 in categoryID 1 while productID 5 is not used anywhere...